regpkg revision 1.9
11.1Sagc#! /bin/sh
21.1Sagc#
31.9Sapb# $NetBSD: regpkg,v 1.9 2006/01/04 14:14:35 apb Exp $
41.1Sagc#
51.1Sagc# Copyright (c) 2003 Alistair G. Crooks.  All rights reserved.
61.1Sagc#
71.1Sagc# Redistribution and use in source and binary forms, with or without
81.1Sagc# modification, are permitted provided that the following conditions
91.1Sagc# are met:
101.1Sagc# 1. Redistributions of source code must retain the above copyright
111.1Sagc#    notice, this list of conditions and the following disclaimer.
121.1Sagc# 2. Redistributions in binary form must reproduce the above copyright
131.1Sagc#    notice, this list of conditions and the following disclaimer in the
141.1Sagc#    documentation and/or other materials provided with the distribution.
151.1Sagc# 3. All advertising materials mentioning features or use of this software
161.1Sagc#    must display the following acknowledgement:
171.1Sagc#	This product includes software developed by Alistair G. Crooks.
181.1Sagc#	for the NetBSD project.
191.1Sagc# 4. The name of the author may not be used to endorse or promote
201.1Sagc#    products derived from this software without specific prior written
211.1Sagc#    permission.
221.1Sagc#
231.1Sagc# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
241.1Sagc# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
251.1Sagc# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
261.1Sagc# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
271.1Sagc# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
281.1Sagc# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
291.1Sagc# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
301.1Sagc# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
311.1Sagc# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
321.1Sagc# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
331.1Sagc# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
341.1Sagc#
351.1Sagc
361.9Sapb# Usage: regpkg [options] set pkgname
371.9Sapb#
381.9Sapb# Registers a syspkg in the database directory,
391.9Sapb# and optionally creates a binary package.
401.9Sapb#
411.9Sapb# Options:
421.9Sapb#   -q		Quiet.
431.9Sapb#   -v		Verbose.
441.9Sapb#   -f		Force.
451.9Sapb#   -m		Ignore errors from missing files.
461.9Sapb#   -u		Update.
471.9Sapb#   -c		Use cached information from ${BUILD_INFO_CACHE}.
481.9Sapb#   -d destdir	Sets DESTDIR.
491.9Sapb#   -t binpkgdir Create a binary package (in *.tgz format) in the
501.9Sapb#		specified directory.  Without this option, a binary
511.9Sapb#		package is not created.
521.9Sapb#   -M metalog	Use the specified metalog file to override file
531.9Sapb#		or directory attributes when creating a binary package.
541.9Sapb#   -N etcdir	Use the specified directory for passwd and group files.
551.9Sapb#
561.9Sapb# When -f is set:  If the desired syspkg already exists, it is overwritten.
571.9Sapb# When -u is set:  If the desired syspkg already exists, it might be
581.9Sapb#		overwritten or left alone, depending on whether it's older
591.9Sapb#		or newer than the files that belong to the syspkg.
601.9Sapb# When neither -u nor -f are set:  It's an error for the desired syspkg
611.9Sapb#		to already exist.
621.1Sagc
631.9Sapbprog="${0##*/}"
641.9Sapbtoppid=$$
651.8Sapbrundir="$(dirname "$0")" # ${0%/*} isn't good enough when there's no "/"
661.9Sapb. "${rundir}/sets.subr"
671.9Sapb
681.9Sapbbomb()
691.9Sapb{
701.9Sapb	#echo "${prog}: bomb: start, toppid=${toppid} \$\$=$$"
711.9Sapb	kill ${toppid}		# in case we were invoked from a subshell
721.9Sapb	#echo "${prog}: bomb: killed ${toppid}"
731.9Sapb	exit 1
741.9Sapb}
751.6Serh
761.9Sapb# A literal newline
771.9Sapbnl='
781.9Sapb'
791.9Sapb# A literal tab
801.9Sapbtab='	'
811.9Sapb
821.9Sapb# Prefixes for error messages, warnings, and important informational
831.9Sapb# messages.
841.9SapbERROR="${prog}: ERROR: "
851.9SapbWARNING="${prog}: WARNING: "
861.9SapbNOTE="${prog}: NOTE: "
871.9SapbERRWARN="${ERROR}"	# may be changed by "-f" (force) command line flag
881.9SapbERRWARNNOTE="${ERROR}"	# may be changed by "-u" (update) command line flag
891.1Sagc
901.9Sapb#
911.9Sapb# All temporary files will go in ${SCRATCH}, which will be deleted on
921.9Sapb# exit.
931.9Sapb#
941.9SapbSCRATCH="$( ${MKTEMP} -d "/var/tmp/${0##*/}.XXXXXX" )"
951.9Sapbif [ $? -ne 0 -o \! -d "${SCRATCH}" ]; then
961.9Sapb	echo >&2 "Could not create scratch directory."
971.9Sapb	bomb
981.1Sagcfi
991.1Sagc
1001.9Sapb#
1011.9Sapb# cleanup() always deletes the SCRATCH directory, and might also
1021.9Sapb# delete other files or directories.
1031.9Sapb#
1041.9Sapbes=0
1051.9Sapbcleanup_must_delete_binpkgfile=false
1061.9Sapbcleanup_must_delete_dbsubdir=false
1071.9Sapbcleanup ()
1081.9Sapb{
1091.9Sapb	trap - 0
1101.9Sapb	#echo "${prog}: cleanup start"
1111.9Sapb	if ${cleanup_must_delete_binpkgfile:-false} && [ -e "${binpkgfile}" ]
1121.9Sapb	then
1131.9Sapb		echo >&2 "${prog}: deleting partially-created ${binpkgfile}"
1141.9Sapb		rm -f "${binpkgfile}"
1151.9Sapb	fi
1161.9Sapb	if ${cleanup_must_delete_dbsubdir:-false} \
1171.9Sapb	   && [ -e "${SYSPKG_DB_SUBDIR}" ]
1181.9Sapb	then
1191.9Sapb		echo >&2 "${prog}: deleting partially-created ${SYSPKG_DB_SUBDIR}"
1201.9Sapb		rm -rf "${SYSPKG_DB_SUBDIR}"
1211.9Sapb	fi
1221.9Sapb	rm -rf "${SCRATCH}"
1231.9Sapb	#echo "${prog}: cleanup done, exit ${es}"
1241.9Sapb	exit ${es}
1251.9Sapb}
1261.9Sapbtrap 'es=128; cleanup' 1 2 3 13 15	# HUP INT QUIT PIPE TERM
1271.9Sapbtrap 'es=$?; cleanup' 0 		# EXIT
1281.9Sapb
1291.9Sapb#
1301.9Sapb# Parse command line args.
1311.9Sapb#
1321.9Sapbverbose=false
1331.9Sapbverbosity=0
1341.9Sapbquiet=false
1351.9Sapbforce=false
1361.9Sapbupdate=false
1371.9Sapballowmissing=false
1381.9SapbDESTDIR="${DESTDIR}"
1391.9Sapbbinpkgdir=""
1401.9Sapbmetalog=""
1411.9Sapbetcdir=""
1421.9SapbSYSPKG_DB_TOPDIR=""
1431.9Sapbpkgset=""
1441.9Sapbpkg=""
1451.9Sapbparse_args ()
1461.9Sapb{
1471.9Sapb	while [ $# -gt 2 ]; do
1481.9Sapb		case "$1" in
1491.9Sapb		-q)	quiet=true ; verbose=false ;;
1501.9Sapb		-v)	verbose=true ; quiet=false
1511.9Sapb			verbosity=$(( ${verbosity} + 1 ))
1521.9Sapb			;;
1531.9Sapb		-f)	force=true ;;
1541.9Sapb		-u)	update=true ;;
1551.9Sapb		-m)	allowmissing=true ;;
1561.9Sapb		-c)	# The -c option is ignored.  The BUILD_INFO_CACHE
1571.9Sapb			# environment variable is used instead.
1581.9Sapb			;;
1591.9Sapb		-d)	DESTDIR="$2" ; shift ;;
1601.9Sapb		-d*)	DESTDIR="${1#-?}" ;;
1611.9Sapb		-t)	binpkgdir="$2" ; shift ;;
1621.9Sapb		-t*)	binpkgdir="${1#-?}" ;;
1631.9Sapb		-M)	metalog="$2" ; shift ;;
1641.9Sapb		-M*)	metalog="${1#-?}" ;;
1651.9Sapb		-N)	etcdir="$2" ; shift ;;
1661.9Sapb		-N*)	etcdir="${1#-?}" ;;
1671.9Sapb		*)	break ;;
1681.9Sapb		esac
1691.9Sapb		shift
1701.9Sapb	done
1711.9Sapb	if ${force}; then
1721.9Sapb		ERRWARN="${WARNING}"
1731.9Sapb	else
1741.9Sapb		ERRWARN="${ERROR}"
1751.9Sapb	fi
1761.9Sapb	if ${update}; then
1771.9Sapb		ERRWARNNOTE="${NOTE}"
1781.9Sapb	else
1791.9Sapb		ERRWARNNOTE="${ERRWARN}"
1801.9Sapb	fi
1811.9Sapb	DESTDIR="${DESTDIR%/}" # delete trailing "/" if any
1821.9Sapb	if [ \! -n "${etcdir}" ]; then
1831.9Sapb		etcdir="${DESTDIR}/etc"
1841.9Sapb	fi
1851.9Sapb	if [ -n "${binpkgdir}" -a \! -d "${binpkgdir}" ]; then
1861.9Sapb		echo >&2 "${ERROR}binary pkg directory ${binpkgdir} does not exist"
1871.9Sapb		bomb
1881.9Sapb	fi
1891.9Sapb	#
1901.9Sapb	# SYSPKG_DB_TOPDIR is the top level directory for registering
1911.9Sapb	# syspkgs.  It defaults to ${DESTDIR}/var/db/syspkg, but can be
1921.9Sapb	# overridden by environment variables SYSPKG_DBDIR or PKG_DBDIR.
1931.9Sapb	#
1941.9Sapb	# Note that this corresponds to the default value of PKG_DBDIR
1951.9Sapb	# set in .../distrib/syspkg/mk/bsd.syspkg.mk.
1961.9Sapb	# 
1971.9Sapb	SYSPKG_DB_TOPDIR="${SYSPKG_DBDIR:-${PKG_DBDIR:-${DESTDIR}/var/db/syspkg}}"
1981.9Sapb
1991.9Sapb	if [ $# -ne 2 ]; then
2001.9Sapb		echo "Usage: regpkg [options] set pkgname"
2011.9Sapb		bomb
2021.9Sapb	fi
2031.9Sapb
2041.9Sapb	pkgset="$1"
2051.9Sapb	pkg="$2"
2061.9Sapb}
2071.1Sagc
2081.9Sapb#
2091.9Sapb# make_PLIST() creates a skeleton PLIST from the pkgset description.
2101.9Sapb#
2111.9Sapb# The result is stored in the file ${PLIST}.
2121.9Sapb#
2131.9SapbPLIST="${SCRATCH}/PLIST"
2141.9Sapbmake_PLIST ()
2151.9Sapb{
2161.9Sapb	if ${verbose} ; then
2171.9Sapb		echo "Making PLIST for \"${pkg}\" package (part of ${pkgset} set)"
2181.9Sapb	fi
2191.9Sapb	prefix="${DESTDIR:-/}"
2201.9Sapb	realprefix=/
2211.9Sapb	${HOST_SH} "${rundir}/makeplist" -p "${prefix}" -I "${realprefix}" \
2221.9Sapb		"${pkgset}" "${pkg}" \
2231.9Sapb		>"${PLIST}" 2>"${SCRATCH}/makeplist-errors"
2241.9Sapb	if ${EGREP} -v '^DEBUG:' "${SCRATCH}/makeplist-errors" ; then
2251.9Sapb		# "find" invoked from makeplist sometimes reports
2261.9Sapb		# errors about missing files or directories, and
2271.9Sapb		# makeplist ignores the errors.  Catch them here.
2281.9Sapb		echo >&2 "${ERROR}makeplist reported errors for ${pkg}:"
2291.9Sapb		cat >&2 "${SCRATCH}/makeplist-errors"
2301.9Sapb		echo >&2 "${ERROR}see above for errors from makeplist"
2311.9Sapb		if ${allowmissing}; then
2321.9Sapb			echo >&2 "${prog}: ${NOTE}: ignoring above errors, due to '-m' option."
2331.9Sapb		else
2341.9Sapb			${force} || bomb
2351.9Sapb		fi
2361.9Sapb	fi
2371.9Sapb}
2381.1Sagc
2391.9Sapb#
2401.9Sapb# init_allfiles() converts the PLIST (which contains relative filenames)
2411.9Sapb# into a list of absolute filenames.  Directories are excluded from the
2421.9Sapb# result.
2431.9Sapb# 
2441.9Sapb# The result is stored in the variable ${allfiles}.
2451.9Sapb#
2461.9Sapballfiles=''
2471.9Sapbinit_allfiles ()
2481.9Sapb{
2491.9Sapb	[ -f "${PLIST}" ] || make_PLIST
2501.9Sapb	allfiles="$( ${AWK} '
2511.9Sapb		BEGIN { destdir = "'"${DESTDIR%/}"'" }
2521.9Sapb		/^@cwd/ { prefix = $2; next }
2531.9Sapb		/^@dirrm/ { next }
2541.9Sapb		{ printf("%s%s%s\n", destdir, prefix, $0) }' "${PLIST}" )"
2551.9Sapb}
2561.1Sagc
2571.9Sapb#
2581.9Sapb# init_newestfile() finds the newest file (most recent mtime).
2591.9Sapb#
2601.9Sapb# The result is stored in the variable ${newestfile}.
2611.9Sapb#
2621.9Sapbnewestfile=''
2631.9Sapbinit_newestfile ()
2641.9Sapb{
2651.9Sapb	[ -s "${allfiles}" ] || init_allfiles
2661.9Sapb	# We assume no shell special characters in ${allfiles},
2671.9Sapb	# and spaces only between file names, not inside file names.
2681.9Sapb	# This should be safe, because it has no no user-specified parts.
2691.9Sapb	newestfile="$( ${LS} -1dt ${allfiles} | ${SED} '1q' )"
2701.9Sapb}
2711.1Sagc
2721.9Sapb#
2731.9Sapb# Various ways of getting parts of the syspkg version number:
2741.9Sapb#
2751.9Sapb# get_osvers() - get the OS version number from osrelease.sh or $(uname -r),
2761.9Sapb#		return it in ${osvers}, and set ${method}.
2771.9Sapb# get_tinyvers() - get the tiny version number from the "versions" file,
2781.9Sapb#		and return it in ${tinyvers}.  Does not set ${method}.
2791.9Sapb# get_newest_rcsid_date() - get the newest RCS date,
2801.9Sapb#		and return it in ${newest}.  Does not set ${method}.
2811.9Sapb# get_newest_mtime_date() - get the newest file modification date,
2821.9Sapb#		and return it in ${newest}.  Does not set ${method}.
2831.9Sapb# get_newest_date() - get date from rcsid or mtime, return it in ${newest},
2841.9Sapb#		and set ${method}.
2851.9Sapb#
2861.9Sapbget_osvers ()
2871.9Sapb{
2881.3Sagc	if [ -f ../../sys/conf/osrelease.sh ]; then
2891.8Sapb		osvers="$(${HOST_SH} ../../sys/conf/osrelease.sh)"
2901.4Sdyoung		method=osreleases
2911.3Sagc	else
2921.8Sapb		osvers="$(${UNAME} -r)"
2931.3Sagc		method=uname
2941.3Sagc	fi
2951.9Sapb	#echo "${osvers}"
2961.9Sapb}
2971.9Sapbget_tinyvers ()
2981.9Sapb{
2991.9Sapb	tinyvers="$( ${AWK} '$1 ~ '/"${pkg}"/' { print $2 }' \
3001.9Sapb			"${rundir}/versions" )"
3011.9Sapb	case "${tinyvers}" in
3021.9Sapb	"")	tinyvers=0
3031.9Sapb		;;
3041.9Sapb	esac
3051.9Sapb	#echo "${tinyvers}"
3061.9Sapb}
3071.9Sapbget_newest_rcsid_date()
3081.9Sapb{
3091.9Sapb	[ -s "${allfiles}" ] || init_allfiles
3101.9Sapb
3111.9Sapb	# Old RCS identifiers might have 2-digit years, so we match both
3121.9Sapb	# YY/MM/DD and YYYY/MM/DD.  We also try to deal with the Y10K
3131.9Sapb	# problem by allowing >4 digit years.
3141.9Sapb	newest=0
3151.9Sapb	case "${allfiles}" in
3161.3Sagc	"")	;;
3171.9Sapb	*)	newest="$( ${IDENT} ${allfiles} 2>/dev/null | ${AWK} '
3181.3Sagc			BEGIN { last = 0 }
3191.3Sagc			$2 == "crt0.c,v" { next }
3201.9Sapb			NF == 8 && \
3211.9Sapb			$4 ~ /^[0-9][0-9]\/[0-9][0-9]\/[0-9][0-9]$/ \
3221.9Sapb				{ t = "19" $4; gsub("/", "", t);
3231.9Sapb				  if (t > last) last = t; }
3241.9Sapb			NF == 8 && \
3251.9Sapb			$4 ~ /^[0-9][0-9][0-9][0-9][0-9]*\/[0-9][0-9]\/[0-9][0-9]$/ \
3261.9Sapb				{ t = $4; gsub("/", "", t);
3271.9Sapb				  if (t > last) last = t; }
3281.9Sapb			END { print last }' )"
3291.3Sagc		method=ident
3301.3Sagc		;;
3311.3Sagc	esac
3321.9Sapb	#echo "${newest}"
3331.9Sapb}
3341.9Sapbget_newest_mtime_date ()
3351.9Sapb{
3361.9Sapb	[ -s "${newestfile}" ] || init_newestfile
3371.9Sapb
3381.9Sapb	# We could simplify the awk program to take advantage of the
3391.9Sapb	# fact thet it should have exactly one line of input.
3401.9Sapb	newest="$( ${ENV_CMD} TZ=UTC LOCALE=C ${LS} -lT "${newestfile}" \
3411.9Sapb		| ${AWK} '
3421.9Sapb		BEGIN { newest = 0 }
3431.9Sapb		{
3441.9Sapb			t = $9 "";
3451.9Sapb			if ($6 == "Jan") t = t "01";
3461.9Sapb			if ($6 == "Feb") t = t "02";
3471.9Sapb			if ($6 == "Mar") t = t "03";
3481.9Sapb			if ($6 == "Apr") t = t "04";
3491.9Sapb			if ($6 == "May") t = t "05";
3501.9Sapb			if ($6 == "Jun") t = t "06";
3511.9Sapb			if ($6 == "Jul") t = t "07";
3521.9Sapb			if ($6 == "Aug") t = t "08";
3531.9Sapb			if ($6 == "Sep") t = t "09";
3541.9Sapb			if ($6 == "Oct") t = t "10";
3551.9Sapb			if ($6 == "Nov") t = t "11";
3561.9Sapb			if ($6 == "Dec") t = t "12";
3571.9Sapb			if ($7 < 10) t = t "0";
3581.9Sapb			t = t $7;
3591.9Sapb			#these next two lines add the 24h clock onto the date
3601.9Sapb			#gsub(":", "", $8);
3611.9Sapb			#t = sprintf("%s.%4.4s", t, $8);
3621.9Sapb			if (t > newest) newest = t;
3631.9Sapb		}
3641.9Sapb		END { print newest }' )"
3651.9Sapb	#echo "${newest}"
3661.9Sapb}
3671.9Sapbget_newest_date ()
3681.9Sapb{
3691.9Sapb	get_newest_rcsid_date
3701.9Sapb	case "${newest}" in
3711.9Sapb	""|0)	get_newest_mtime_date
3721.3Sagc		method=ls
3731.3Sagc		;;
3741.9Sapb	*)	method=rcsid
3751.9Sapb		;;
3761.3Sagc	esac
3771.9Sapb	#echo "${newest}"
3781.9Sapb}
3791.9Sapb
3801.9Sapb#
3811.9Sapb# choose_version_number() chooses the syspkg version number,
3821.9Sapb# by concatenating several components (OS version, syspkg "tiny"
3831.9Sapb# version and date).  We end up with something like
3841.9Sapb# osvers="3.99.15", tinyvers="0", newest="20060104",
3851.9Sapb# and t="3.99.15.0.20060104".
3861.9Sapb#
3871.9Sapb# The result is stored in the variables ${t} and ${method}.
3881.9Sapb#
3891.9Sapbmethod=''
3901.9Sapbt=''
3911.9Sapbchoose_version_number ()
3921.9Sapb{
3931.9Sapb	get_osvers ; m1="${method}"
3941.9Sapb	get_tinyvers # does not set ${method}
3951.9Sapb	get_newest_date ; m2="${method}"
3961.9Sapb	t="${osvers}.${tinyvers}.${newest}"
3971.9Sapb	method="${m1}.${m2}"
3981.9Sapb
3991.9Sapb	# print version number that we're using
4001.9Sapb	if ${verbose}; then
4011.9Sapb		echo "${pkg} - ${t} version using ${method} method"
4021.9Sapb	fi
4031.9Sapb}
4041.9Sapb
4051.9Sapb#
4061.9Sapb# print_dir_exec_lines outputs an "@exec install" line for each
4071.9Sapb# directory in ${PLIST}
4081.9Sapb#
4091.9Sapbprint_dir_exec_lines ()
4101.9Sapb{
4111.9Sapb	local dir uname gname mode
4121.9Sapb	local dot_slash_dir
4131.9Sapb	local no_dot_dir
4141.9Sapb	local word line
4151.9Sapb	${AWK} '/^@dirrm/ { print $2 }' <"${PLIST}" | \
4161.9Sapb	${SORT} | \
4171.9Sapb	while read dir ; do
4181.9Sapb		# Sanitise the name. ${dir} could be an absolute or
4191.9Sapb		# relative name, with or without a leading "./".
4201.9Sapb		# ${dot_slash_dir} always has a leading "./" (except when
4211.9Sapb		# it's exactly equal to "."). ${no_dot_dir} never has a
4221.9Sapb		# leading "." or "/" (except when it's exactly equal to
4231.9Sapb		# ".").
4241.9Sapb		case "${dir}" in
4251.9Sapb		.|./|/)	dot_slash_dir=.  ;;
4261.9Sapb		./*)	dot_slash_dir="${dir}" ;;
4271.9Sapb		/*)	dot_slash_dir=".${dir}" ;;
4281.9Sapb		*)	dot_slash_dir="./${dir}" ;;
4291.9Sapb		esac
4301.9Sapb		no_dot_dir="${dot_slash_dir#./}"
4311.9Sapb		# Get the directory's owner, group, and mode
4321.9Sapb		# from the live file system, or let it be overridden
4331.9Sapb		# by the metalog.
4341.9Sapb		eval "$( ${STAT} -f 'uname=%Su gname=%Sg mode=%#OLp' \
4351.9Sapb				"${DESTDIR}/${dot_slash_dir}" )"
4361.9Sapb		if [ -n "${metalog}" ]; then
4371.9Sapb			line="$( echo "${dot_slash_dir}" | \
4381.9Sapb				${AWK} -f "${rundir}/join.awk" \
4391.9Sapb					/dev/stdin "${metalog}" )"
4401.9Sapb			for word in ${line} ; do
4411.9Sapb				case "${word}" in
4421.9Sapb				uname=*|gname=*|mode=*)	eval "${word}" ;;
4431.9Sapb				esac
4441.9Sapb			done
4451.9Sapb		fi
4461.9Sapb		# XXX: Work around yet another pkg_add bug: @cwd lines
4471.9Sapb		# do not actually cause the working directory to change,
4481.9Sapb		# so file names in @exec lines need to be qualified by
4491.9Sapb		# %D, which (in our case, since we know there's an
4501.9Sapb		# "@cwd /" line) will be the dir name passed to
4511.9Sapb		# "pkg_add -p PREFIX".
4521.9Sapb		case "${no_dot_dir}" in
4531.9Sapb		.) d="%D" ;;
4541.9Sapb		*) d="%D/${no_dot_dir}" ;;
4551.9Sapb		esac
4561.9Sapb		cat <<EOF
4571.9Sapb@exec install -d -o ${uname} -g ${gname} -m ${mode} ${d}
4581.9SapbEOF
4591.9Sapb	done
4601.9Sapb}
4611.2Sjwise
4621.9Sapb#
4631.9Sapb# register_syspkg() registers the syspkg in ${SYSPKG_DB_TOPDIR}.
4641.9Sapb# This involves creating the subdirectory ${SYSPKG_DB_SUBDIR}
4651.9Sapb# and populating it with several files.
4661.9Sapb#
4671.9Sapbregister_syspkg ()
4681.9Sapb{
4691.9Sapb	cleanup_must_delete_dbsubdir=true
4701.9Sapb	[ -n "${SYSPKG_DB_SUBDIR}" ] || bomb
4711.9Sapb	mkdir -p "${SYSPKG_DB_SUBDIR}"
4721.9Sapb
4731.9Sapb	#
4741.9Sapb	# Guess what versions of other packages to depend on.
4751.9Sapb	#
4761.9Sapb	# If we are using the OS version as part of the pkg
4771.9Sapb	# version, then depend on any version ">=${osvers}".  For
4781.9Sapb	# example, etc-sys-etc-1.6ZI.0.20040206 might depend on
4791.9Sapb	# base-sys-root>=1.6ZI.
4801.9Sapb	#
4811.9Sapb	# Failing that, depend on any version "-[0-9]*".
4821.9Sapb	#
4831.9Sapb	# XXX: We could extend the format of the "deps" file to carry
4841.9Sapb	# this sort of information, so we wouldn't have to guess.
4851.9Sapb	#
4861.9Sapb	case "${t}" in
4871.9Sapb	${osvers}.*)	depversion=">=${osvers}" ;;
4881.9Sapb	*)		depversion="-[0-9]*" ;;
4891.9Sapb	esac
4901.9Sapb
4911.9Sapb	#
4921.9Sapb	# Add the dependencies.
4931.9Sapb	#
4941.9Sapb	# We always add a "@pkgdep" line for each prerequisite package.
4951.9Sapb	#
4961.9Sapb	# If the prerequisite pkg is already registered (as it should be
4971.9Sapb	# if our caller is doing things in the right order), then we put
4981.9Sapb	# its exact version number in a "@blddep" line.
4991.9Sapb	#
5001.9Sapb	${AWK} '$1 ~ '/"${pkg}"/' { print $2 }' "${rundir}/deps" | ${SORT} | \
5011.9Sapb	while read depname ; do
5021.9Sapb		# ${pkgdepglob} is a shell glob pattern that should match
5031.9Sapb		# any version of a pkg.  ${pkgdep} uses the special syntax
5041.9Sapb		# for pkg dependencies, and is not usable as a shell
5051.9Sapb		# glob pattern.
5061.9Sapb		pkgdepglob="${depname}-[0-9]*"
5071.9Sapb		pkgdep="${depname}${depversion}"
5081.9Sapb		echo "@pkgdep ${pkgdep}"
5091.9Sapb		blddep="$( cd "${SYSPKG_DB_TOPDIR}" && echo ${pkgdepglob} \
5101.9Sapb			|| bomb )"
5111.9Sapb		case "${blddep}" in
5121.9Sapb		*\*)	# pkgdepglob did not match anything
5131.9Sapb			echo >&2 "${WARNING}${pkg} depends on '${pkgdep}' but there is no matching syspkg in ${SYSPKG_DB_TOPDIR}"
5141.9Sapb			;;
5151.9Sapb		*\ *)	# pkgdepglob matched more than once.
5161.9Sapb			echo >&2 "${ERRWARN}${pkg} depends on '${pkgdep}' but there are multiple matching syspkgs in ${SYSPKG_DB_TOPDIR}"
5171.9Sapb			${force} || bomb
5181.9Sapb			# If ${force} is set, then assume that the last
5191.9Sapb			# match is the most recent.
5201.9Sapb			# XXX: This might be wrong, because of
5211.9Sapb			# differences between lexical sorting and
5221.9Sapb			# numeric sorting.
5231.9Sapb			lastmatch="${blddep##* }"
5241.9Sapb			echo "@blddep ${lastmatch}"
5251.9Sapb			;;
5261.9Sapb		*)	# exactly one match.
5271.9Sapb			# XXX: We ignore the possibility that the
5281.9Sapb			# version we found via ${pkgdepglob} might not
5291.9Sapb			# satisfy ${pkgdep}.  We could conceivably use
5301.9Sapb			# "pkg_admin pmatch" to check, but that's not a
5311.9Sapb			# host tool so we can't assume that it will be
5321.9Sapb			# available.
5331.9Sapb			echo "@blddep ${blddep}"
5341.9Sapb			;;
5351.9Sapb		esac
5361.9Sapb	done >>"${PLIST}"
5371.9Sapb
5381.9Sapb	# create the comment (should be one line)
5391.9Sapb	comment="$( ${AWK} '$1 ~ '/"${pkg}"/' \
5401.9Sapb			{ print substr($0, length($1) + 2) }' \
5411.9Sapb			"${rundir}/comments" )"
5421.9Sapb	case "${comment}" in
5431.9Sapb	"")	echo >&2 "${WARNING}no comment for \"${pkg}\" (using placeholder)"
5441.9Sapb		comment="System package for ${pkg}"
5451.9Sapb		;;
5461.9Sapb	*"${nl}"*)
5471.9Sapb		echo >&2 "${ERRWARN}multi-line comment for \"${pkg}\""
5481.9Sapb		${force} || bomb
5491.9Sapb		;;
5501.9Sapb	esac
5511.9Sapb	echo "${comment}" > "${SYSPKG_DB_SUBDIR}/+COMMENT"
5521.1Sagc
5531.9Sapb	# create the description (could be multiple lines)
5541.9Sapb	descr="$( ${AWK} '$1 ~ '/"${pkg}"/' {
5551.9Sapb			print substr($0, length($1) + 2) }' \
5561.9Sapb			"${rundir}/descrs" )"
5571.9Sapb	case "${descr}" in
5581.9Sapb	"")	echo >&2 "${WARNING}no description for \"${pkg}\" (re-using comment)" 2>&1
5591.9Sapb		descr="${comment}"
5601.9Sapb		;;
5611.9Sapb	esac
5621.9Sapb	echo "${descr}" > "${SYSPKG_DB_SUBDIR}/+DESC"
5631.9Sapb	${PRINTF} "\nHomepage:\nhttp://www.NetBSD.org/\n" >> "${SYSPKG_DB_SUBDIR}/+DESC"
5641.1Sagc
5651.9Sapb	# create the build information
5661.9Sapb	if [ x"${BUILD_INFO_CACHE}" = x ]; then
5671.9Sapb		{
5681.9Sapb		# These variables describe the build
5691.9Sapb		# environment, not the target.
5701.9Sapb		echo "OPSYS=$(${UNAME} -s)"
5711.9Sapb		echo "OS_VERSION=$(${UNAME} -r)"
5721.9Sapb		${MAKE} -f- all <<EOF
5731.4Sdyoung.include <bsd.own.mk>
5741.4Sdyoungall:
5751.4Sdyoung	@echo OBJECT_FMT=${OBJECT_FMT}
5761.4Sdyoung	@echo MACHINE_ARCH=${MACHINE_ARCH}
5771.4Sdyoung	@echo MACHINE_GNU_ARCH=${MACHINE_GNU_ARCH}
5781.4SdyoungEOF
5791.9Sapb		# XXX: what's the point of reporting _PKGTOOLS_VER
5801.9Sapb		# when we roll everything by hand without using
5811.9Sapb		# the pkg tools?
5821.9Sapb		echo "_PKGTOOLS_VER=$(${PKG_CREATE} -V)"
5831.9Sapb		} > "${SYSPKG_DB_SUBDIR}/+BUILD_INFO"
5841.9Sapb	else
5851.9Sapb		cp "${BUILD_INFO_CACHE}" "${SYSPKG_DB_SUBDIR}/+BUILD_INFO"
5861.9Sapb	fi
5871.9Sapb
5881.9Sapb	# test for attributes
5891.9Sapb	args=""
5901.9Sapb	attrs="$( ${AWK} '$1 ~ '/"${pkg}"/' { \
5911.9Sapb			print substr($0, length($1) + 2) }' \
5921.9Sapb		"${rundir}/attrs" )"
5931.9Sapb	for a in "${attrs}"; do
5941.9Sapb		case "${attrs}" in
5951.9Sapb		"")	;;
5961.9Sapb		preserve)
5971.9Sapb			echo "${pkg}-${t}" >"${SYSPKG_DB_SUBDIR}/+PRESERVE"
5981.9Sapb			args="${args} -n ${SYSPKG_DB_SUBDIR}/+PRESERVE"
5991.9Sapb			;;
6001.9Sapb		esac
6011.9Sapb	done
6021.9Sapb
6031.9Sapb	#
6041.9Sapb	# Create ${SYSPKGSIR}/+CONTENTS from ${PLIST}, by adding an
6051.9Sapb	# "@name" line and a lot of "@comment MD5:" lines.
6061.9Sapb	#
6071.9Sapb	{
6081.9Sapb		rcsid='$NetBSD: regpkg,v 1.9 2006/01/04 14:14:35 apb Exp $'
6091.9Sapb		utcdate="$( ${ENV_CMD} TZ=UTC LOCALE=C \
6101.9Sapb			${DATE} '+%Y-%m-%d %H:%M' )"
6111.9Sapb		user="${USER:-root}"
6121.9Sapb		host="$( ${HOSTNAME} )"
6131.9Sapb		echo "@name ${pkg}-${t}"
6141.9Sapb		echo "@comment Packaged at ${utcdate} UTC by ${user}@${host}"
6151.9Sapb		echo "@comment Packaged using ${prog} ${rcsid}"
6161.9Sapb		# XXX: "option extract-in-place" might help to get
6171.9Sapb		#	pkg_add to create directories.
6181.9Sapb		# XXX: no, it doesn't work.  Yet another pkg_add bug.
6191.9Sapb		## echo "@option extract-in-place"
6201.9Sapb		# Move the @pkgdep and @blddep lines up, so that
6211.9Sapb		# they are easy to see when people do "less
6221.9Sapb		# ${DESTDIR}/var/db/syspkg/*/+CONTENTS".
6231.9Sapb		${EGREP} '^(@pkgdep|@blddep)' "${PLIST}" || true
6241.9Sapb		# Now do the remainder of the file.
6251.9Sapb		while read line ; do
6261.9Sapb			case "${line}" in
6271.9Sapb			@pkgdep*|@blddep*)
6281.9Sapb				# already handled by grep above
6291.9Sapb				;;
6301.9Sapb			@cwd*)
6311.9Sapb				# There should be exactly one @cwd line.
6321.9Sapb				# Just after it, add an "@exec mkdir"
6331.9Sapb				# line for every directory.  This is to
6341.9Sapb				# work around a pkg-add bug (see
6351.9Sapb				# <http://mail-index.NetBSD.org/tech-pkg/2003/12/11/0018.html>)
6361.9Sapb				echo "${line}"
6371.9Sapb				print_dir_exec_lines
6381.9Sapb				;;
6391.9Sapb			@*)	
6401.9Sapb				# just pass through all other @foo lines
6411.9Sapb				echo "${line}"
6421.9Sapb				;;
6431.9Sapb			*)	
6441.9Sapb				# This should be a file name.  Pass it
6451.9Sapb				# through, and append "@comment MD5:".
6461.9Sapb				# XXX why not SHA256 ?
6471.9Sapb				echo "${line}"
6481.9Sapb				file="${DESTDIR}${line}"
6491.9Sapb				if [ -f "${file}" -a -r "${file}" ];
6501.9Sapb				then
6511.9Sapb					md5sum="$( ${CKSUM} -n -m "${file}" \
6521.9Sapb						   | ${AWK} '{print $1}'
6531.9Sapb						)"
6541.9Sapb					echo "@comment MD5:${md5sum}"
6551.9Sapb				fi
6561.9Sapb				;;
6571.9Sapb			esac
6581.9Sapb		done <"${PLIST}"
6591.9Sapb	} >"${SYSPKG_DB_SUBDIR}/+CONTENTS"
6601.9Sapb
6611.9Sapb	#
6621.9Sapb	#  Update ${SYSPKG_DB_TOPDIR}/pkgdb.byfile.db.
6631.9Sapb	#
6641.9Sapb	{
6651.9Sapb		dbfile="${SYSPKG_DB_TOPDIR}/pkgdb.byfile.db"
6661.9Sapb		dbtype="btree"
6671.9Sapb		db_opts=''
6681.9Sapb		# XXX: cross builds should really add "-E B" or "-E L"
6691.9Sapb		# (big-endian or little-endian) to db_opts, but we don't
6701.9Sapb		# do that yet.
6711.9Sapb		if ${update} || ${force} ; then
6721.9Sapb			# overwriting an existing entry is not an error
6731.9Sapb			db_opts="${db_opts} -R"
6741.9Sapb		fi
6751.9Sapb		if [ ${verbosity} -lt 2 ]; then
6761.9Sapb			# don't print all the keys added to the database
6771.9Sapb			db_opts="${db_opts} -q"
6781.9Sapb		fi
6791.9Sapb
6801.9Sapb		# Transform ${PLIST} into a form to be used as keys in
6811.9Sapb		# ${dbfile}.  The results look like absolute paths,
6821.9Sapb		# but they are really relative to ${DESTDIR}.
6831.9Sapb		#
6841.9Sapb		# "@dirrm ."		-> "/"
6851.9Sapb		# "@dirrm foo/bar"	-> "/foo/bar"
6861.9Sapb		# "@dirrm ./foo/bar"	-> "/foo/bar"
6871.9Sapb		# "foo/bar/baz"		-> "/foo/bar/baz"
6881.9Sapb		# "./foo/bar/baz"	-> "/foo/bar/baz"
6891.9Sapb		#
6901.9Sapb		dblist="${SCRATCH}/dblist"
6911.9Sapb		${AWK} '/^@dirrm \.\//	{gsub("^.", "", $2); print $2; next}
6921.9Sapb			/^@dirrm \.$/	{print "/"; next}
6931.9Sapb			/^@dirrm/	{print "/" $2; next}
6941.9Sapb			/^@/		{next}
6951.9Sapb			/^\.\//		{gsub("^.", "", $0); print $0; next}
6961.9Sapb			/./		{print "/" $0; next}' \
6971.9Sapb			<"${PLIST}" >"${dblist}"
6981.9Sapb		# Add all the path names to the database.
6991.9Sapb		${AWK} '{print $1 "\t" "'"${pkg}-${t}"'"}' <"${dblist}" \
7001.9Sapb		| ${DB} -w ${db_opts} -F "${tab}" -f - "${dbtype}" "${dbfile}"
7011.9Sapb	}
7021.9Sapb
7031.9Sapb	if ${verbose} ; then
7041.9Sapb		echo "Registered ${pkg}-${t} in ${SYSPKG_DB_TOPDIR}"
7051.9Sapb	elif ! ${quiet} ; then
7061.9Sapb		echo "Registered ${pkg}-${t}"
7071.9Sapb	fi
7081.9Sapb
7091.9Sapb	cleanup_must_delete_dbsubdir=false
7101.9Sapb}
7111.9Sapb
7121.9Sapb#
7131.9Sapb# create_syspkg_tgz() creates the *.tgz file for the package.
7141.9Sapb#
7151.9Sapb# The output file is ${binpkgdir}/${pkg}-${t}.tgz.
7161.9Sapb#
7171.9Sapbcreate_syspkg_tgz ()
7181.9Sapb{
7191.9Sapb	#
7201.9Sapb	# pkg_create does not understand metalog files, so we have to
7211.9Sapb	# use pax directly.
7221.9Sapb	#
7231.9Sapb	# We create two specfiles: specfile_overhead describes the
7241.9Sapb	# special files that are part of the package system's metadata
7251.9Sapb	# (+CONTENTS, +COMMENT, +DESCR, and more); and specfile_payload
7261.9Sapb	# describes the files and directories that we actually want as
7271.9Sapb	# part of the package's payload.
7281.9Sapb	#
7291.9Sapb	# We then use the specfiles to create a compressed tarball that
7301.9Sapb	# contains both the overhead files and the payload files.
7311.9Sapb	#
7321.9Sapb	# There's no trivial way to get a single pax run to do
7331.9Sapb	# everything we want, so we run pax twice, with a different
7341.9Sapb	# working directory and a different specfile each time.
7351.9Sapb	#
7361.9Sapb	# We could conceivably make clever use of pax's "-s" option to
7371.9Sapb	# get what we want from a single pax run with a single (more
7381.9Sapb	# complicated) specfile, but the extra trouble doesn't seem
7391.9Sapb	# warranted.
7401.9Sapb	#
7411.9Sapb	cleanup_must_delete_binpkgfile=true
7421.9Sapb	specfile_overhead="${SCRATCH}/spec_overhead"
7431.9Sapb	specfile_payload="${SCRATCH}/spec_payload"
7441.9Sapb	tarball_uncompressed="${SCRATCH}/tarball_uncompressed"
7451.9Sapb
7461.9Sapb	# Create a specfile for all the overhead files (+CONTENTS and
7471.9Sapb	# friends).
7481.9Sapb	{
7491.9Sapb		plusnames_first="${SCRATCH}/plusnames_first"
7501.9Sapb		plusnames_rest="${SCRATCH}/plusnames_rest"
7511.9Sapb
7521.9Sapb		# Ensure that the first few files are in the same order
7531.9Sapb		# that "pkg_create" would have used, just in case anything
7541.9Sapb		# depends on that.  Other files in alphabetical order.
7551.9Sapb		SHOULD_BE_FIRST="+CONTENTS +COMMENT +DESC"
7561.9Sapb		(
7571.9Sapb			cd "${SYSPKG_DB_SUBDIR}" || bomb
7581.9Sapb			for file in ${SHOULD_BE_FIRST}; do
7591.9Sapb				[ -e "./${file}" ] && echo "${file}"
7601.9Sapb			done >"${plusnames_first}"
7611.9Sapb			${LS} -1 | ${FGREP} -v -f "${plusnames_first}" \
7621.9Sapb				>"${plusnames_rest}" \
7631.9Sapb				|| true
7641.9Sapb		)
7651.9Sapb
7661.9Sapb		# Convert the file list to specfile format, and override the
7671.9Sapb		# uid/gid/mode.
7681.9Sapb		{
7691.9Sapb			echo ". optional type=dir"
7701.9Sapb			${AWK} '{print "./" $0 " type=file uid=0 gid=0 mode=0444"
7711.9Sapb				}' "${plusnames_first}" "${plusnames_rest}"
7721.9Sapb		} >"${specfile_overhead}"
7731.9Sapb	}
7741.9Sapb
7751.9Sapb	# Create a specfile for the payload of the package.
7761.9Sapb	{
7771.9Sapb		spec1="${SCRATCH}/spec1"
7781.9Sapb		spec2="${SCRATCH}/spec2"
7791.9Sapb
7801.9Sapb		# Transform ${PLIST} into simple specfile format:
7811.9Sapb		#
7821.9Sapb		# "@dirrm ."		-> "."
7831.9Sapb		# "@dirrm foo/bar"	-> "./foo/bar"
7841.9Sapb		# "@dirrm ./foo/bar"	-> "./foo/bar"
7851.9Sapb		# "foo/bar/baz"		-> "./foo/bar/baz"
7861.9Sapb		# "./foo/bar/baz"	-> "./foo/bar/baz"
7871.9Sapb		#
7881.9Sapb		# Ignores @cwd lines.  This should be safe, given how
7891.9Sapb		# makeplist works.
7901.9Sapb		${AWK} '/^@dirrm \.\//	{print $2; next}
7911.9Sapb			/^@dirrm \.$/	{print "."; next}
7921.9Sapb			/^@dirrm/	{print "./" $2; next}
7931.9Sapb			/^@/		{next}
7941.9Sapb			/^\.\//		{print $0; next}
7951.9Sapb			/./		{print "./" $0; next}' \
7961.9Sapb			<"${PLIST}" >"${spec1}"
7971.9Sapb
7981.9Sapb		# If metalog was specified, attributes from metalog override
7991.9Sapb		# attributes in the file system.  We also fake up an
8001.9Sapb		# entry for the ./etc/mtree/set.${pkgset} file.
8011.9Sapb		{
8021.9Sapb			if [ -n "${metalog}" ]; then
8031.9Sapb				${AWK} -f "${rundir}/join.awk" \
8041.9Sapb					"${spec1}" "${metalog}"
8051.9Sapb				${AWK} -f "${rundir}/join.awk" \
8061.9Sapb					"${spec1}" /dev/stdin <<EOF
8071.9Sapb./etc/mtree/set.${pkgset} type=file mode=0444 uname=root gname=wheel
8081.9SapbEOF
8091.9Sapb			else
8101.9Sapb				cat "${spec1}"
8111.9Sapb			fi
8121.9Sapb		} >"${spec2}"
8131.9Sapb
8141.9Sapb		#
8151.9Sapb		# If a file or directory to was mentioned explicitly
8161.9Sapb		# in ${PLIST} but not mentioned in ${metalog}, then the
8171.9Sapb		# file or directory will not be mentioned in ${spec2}.
8181.9Sapb		# This is an error, and means that the metalog was
8191.9Sapb		# not built correctly.
8201.9Sapb		#
8211.9Sapb		if [ -n "${metalog}" ]; then
8221.9Sapb			names1="${SCRATCH}/names1"
8231.9Sapb			names2="${SCRATCH}/names2"
8241.9Sapb			${AWK} '{print $1}' <"${spec1}" | ${SORT} >"${names1}"
8251.9Sapb			${AWK} '{print $1}' <"${spec2}" | ${SORT} >"${names2}"
8261.9Sapb			if ${FGREP} -v -f "${names2}" "${spec1}" >/dev/null
8271.9Sapb			then
8281.9Sapb				cat >&2 <<EOM
8291.9Sapb${ERRWARN}The metalog file (${metalog}) does not
8301.9Sapb	contain entries for the following files or directories
8311.9Sapb	which should be part of the ${pkg} syspkg:
8321.9SapbEOM
8331.9Sapb				${FGREP} -v -f "${names2}" "${spec1}" >&2
8341.9Sapb				${force} || bomb
8351.9Sapb			fi
8361.9Sapb			if ${FGREP} -v -f "${names1}" "${spec2}" >/dev/null
8371.9Sapb			then
8381.9Sapb				cat >&2 <<EOM
8391.9Sapb${ERRWARN}The following lines are in the metalog file
8401.9Sapb	(${metalog}), and the corresponding files or directories
8411.9Sapb	should be in the ${pkg} syspkg, but something is wrong:
8421.9SapbEOM
8431.9Sapb				${FGREP} -v -f "${names1}" "${spec2}" >&2
8441.9Sapb				bomb
8451.9Sapb			fi
8461.9Sapb		fi
8471.9Sapb
8481.9Sapb		# Add lines (tagged "optional") for any implicit directories.
8491.9Sapb		#
8501.9Sapb		# For example, if we have a file ./foo/bar/baz, then we add
8511.9Sapb		# "./foo/bar optional type=dir", "./foo optional type=dir",
8521.9Sapb		# and ". optional type=dir", unless those directories were
8531.9Sapb		# already mentioned explicitly.
8541.9Sapb		#
8551.9Sapb		${AWK} -f "${rundir}/getdirs.awk" "${spec2}" \
8561.9Sapb		| ${SORT} -u >"${specfile_payload}"
8571.9Sapb	}
8581.9Sapb
8591.9Sapb	# Use two pax invocations followed by gzip to create
8601.9Sapb	# the tgz file.
8611.9Sapb	#
8621.9Sapb	# Remove any leading "./" from path names, because that
8631.9Sapb	# could confuse tools that work with binary packages.
8641.9Sapb	(
8651.9Sapb		cd "${SYSPKG_DB_SUBDIR}" && \
8661.9Sapb		${PAX} -O -w -d -N"${etcdir}" -M '-s,^\./,,' \
8671.9Sapb			-f "${tarball_uncompressed}" \
8681.9Sapb			<"${specfile_overhead}" \
8691.9Sapb		|| bomb
8701.9Sapb	)
8711.9Sapb	(
8721.9Sapb		cd "${DESTDIR:-/}" && \
8731.9Sapb		${PAX} -O -w -d -N"${etcdir}" -M '-s,^\./,,' \
8741.9Sapb			-a -f "${tarball_uncompressed}" \
8751.9Sapb			<"${specfile_payload}" \
8761.9Sapb		|| bomb
8771.9Sapb	)
8781.9Sapb	${GZIP_CMD} -9 <"${tarball_uncompressed}" >"${binpkgfile}" || bomb
8791.9Sapb
8801.9Sapb	# (Extra space is to make message line up with "Registered" message.)
8811.9Sapb	if ${verbose} ; then
8821.9Sapb		echo "  Packaged ${binpkgfile}"
8831.9Sapb	elif ! ${quiet} ; then
8841.9Sapb		echo "  Packaged ${binpkgfile##*/}"
8851.9Sapb	fi
8861.9Sapb
8871.9Sapb	cleanup_must_delete_binpkgfile=false
8881.9Sapb
8891.9Sapb}
8901.9Sapb
8911.9Sapb#
8921.9Sapb# do_register_syspkg() registers the syspkg if appropriate.
8931.9Sapb#
8941.9Sapb# If SYSPKG_DB_SUBDIR already exists, that might be an error, depending
8951.9Sapb# on ${force} and ${update} flags.
8961.9Sapb#
8971.9Sapbdo_register_syspkg ()
8981.9Sapb{
8991.9Sapb	# Check that necessary variables are defined
9001.9Sapb	[ -n "${SYSPKG_DB_TOPDIR}" ] || bomb
9011.9Sapb	[ -n "${SYSPKG_DB_SUBDIR}" ] || bomb
9021.9Sapb
9031.9Sapb	# Create SYSPKG_DB_TOPDIR if necessary
9041.9Sapb	[ -d "${SYSPKG_DB_TOPDIR}" ] || mkdir -p "${SYSPKG_DB_TOPDIR}" || bomb
9051.9Sapb
9061.9Sapb	# A function to delete and re-register a syspkg
9071.9Sapb	delete_and_reregister ()
9081.9Sapb	{
9091.9Sapb		echo >&2 "${ERRWARNNOTE}deleting and re-registering ${pkg}-${t}"
9101.9Sapb		cleanup_must_delete_dbsubdir=true
9111.9Sapb		rm -rf "${SYSPKG_DB_SUBDIR}"
9121.9Sapb		register_syspkg
9131.9Sapb	}
9141.9Sapb
9151.9Sapb	# Check whether another version of ${pkg} is already registered.
9161.9Sapb	pattern="${pkg}-[0-9]*"
9171.9Sapb	matches="$( cd "${SYSPKG_DB_TOPDIR}" && echo ${pattern} || bomb )"
9181.9Sapb	case "${matches}" in
9191.9Sapb	*\*)		;;	# wildcard did not match anything
9201.9Sapb	"${pkg}-${t}")	;;	# exact match
9211.9Sapb	*)	echo >&2 "${ERRWARN}another version of ${pkg} is already registered in ${SYSPKG_DB_TOPDIR} (while creating ${pkg}-${t})"
9221.9Sapb		${force} || bomb
9231.9Sapb		;;
9241.9Sapb	esac
9251.9Sapb
9261.9Sapb	# Check whether the desired version of ${pkg} is already registered,
9271.9Sapb	# and create it if appropriate.
9281.9Sapb	if [ -d "${SYSPKG_DB_SUBDIR}" ]; then
9291.9Sapb		echo >&2 "${ERRWARNNOTE}${pkg}-${t} is already registered"
9301.9Sapb		${verbose} && echo >&2 "	in ${SYSPKG_DB_TOPDIR}"
9311.9Sapb		if ${force}; then
9321.9Sapb			delete_and_reregister
9331.9Sapb		elif ${update}; then
9341.9Sapb			#
9351.9Sapb			# If all files in SYSPKG_DB_SUBDIR are newer
9361.9Sapb			# than all files in the pkg, then do nothing.
9371.9Sapb			# Else delete and re-register the pkg.
9381.9Sapb			#
9391.9Sapb			[ -n "${newestfile}" ] || init_newestfile
9401.9Sapb			if [ -n "${newestfile}" ]; then
9411.9Sapb				case "$( ${FIND} "${SYSPKG_DB_SUBDIR}" -type f \
9421.9Sapb					! -newer "${newestfile}" -print )" \
9431.9Sapb				in
9441.9Sapb				"")	;;
9451.9Sapb				*)	delete_and_reregister ;;
9461.9Sapb				esac
9471.9Sapb
9481.9Sapb			else
9491.9Sapb				# No files in the pkg?  (This could happen
9501.9Sapb				# if a pkg contains only directories.)
9511.9Sapb				# Do nothing.
9521.9Sapb			fi
9531.9Sapb		else
9541.9Sapb			bomb
9551.9Sapb		fi
9561.9Sapb	else
9571.9Sapb		register_syspkg
9581.9Sapb	fi
9591.9Sapb}
9601.9Sapb
9611.9Sapb#
9621.9Sapb# do_create_syspkg_tgz() creates the the binary pkg (*.tgz) if
9631.9Sapb# appropriate.
9641.9Sapb#
9651.9Sapb# If binpkgfile already exists, that might be an error, depending on
9661.9Sapb# ${force} and ${update} flags.
9671.9Sapb#
9681.9Sapbdo_create_syspkg_tgz ()
9691.9Sapb{
9701.9Sapb	[ -n "${binpkgfile}" ] || bomb
9711.9Sapb
9721.9Sapb	delete_and_recreate ()
9731.9Sapb	{
9741.9Sapb		echo >&2 "${ERRWARNNOTE}deleting and re-creating ${pkg}-${t}.tgz"
9751.9Sapb		rm -f "${binpkgfile}"
9761.9Sapb		create_syspkg_tgz
9771.9Sapb	}
9781.9Sapb
9791.9Sapb	# Check whether another version of ${pkg} already exists.
9801.9Sapb	pattern="${pkg}-[0-9]*"
9811.9Sapb	matches="$( cd "${binpkgdir}" && echo ${pattern} || bomb )"
9821.9Sapb	case "${matches}" in
9831.9Sapb	*\*)	;;	# wildcard did not match anything
9841.9Sapb	"${pkg}-${t}.tgz") ;;	# exact match
9851.9Sapb	*)	echo >&2 "${ERRWARN}another version of ${pkg} already exists in ${binpkgdir} (while creating ${pkg}-${t}.tgz)"
9861.9Sapb		${force} || bomb
9871.9Sapb		;;
9881.9Sapb	esac
9891.9Sapb
9901.9Sapb	# Check whether the desired version of ${pkg} already exists,
9911.9Sapb	# and create it if appropriate.
9921.9Sapb	if [ -e "${binpkgfile}" ]; then
9931.9Sapb		echo >&2 "${ERRWARNNOTE}${pkg}-${t}.tgz already exists"
9941.9Sapb		${verbose} && echo >&2 "	in ${binpkgdir}"
9951.9Sapb		if ${force}; then
9961.9Sapb			delete_and_recreate
9971.9Sapb		elif ${update}; then
9981.9Sapb			#
9991.9Sapb			# If all files in SYSPKG_DB_SUBDIR are older
10001.9Sapb			# than ${binpkgfile}, then do nothing.
10011.9Sapb			# Else delete and re-create the tgz.
10021.9Sapb			#
10031.9Sapb			case "$( ${FIND} "${SYSPKG_DB_SUBDIR}" -type f \
10041.9Sapb				-newer "${binpkgfile}" -print )" \
10051.9Sapb			in
10061.9Sapb			"")	;;
10071.9Sapb			*)	delete_and_recreate ;;
10081.9Sapb			esac
10091.9Sapb		else
10101.9Sapb			bomb
10111.9Sapb		fi
10121.9Sapb	else
10131.9Sapb		create_syspkg_tgz
10141.9Sapb	fi
10151.9Sapb}
10161.9Sapb
10171.9Sapb####################
10181.9Sapb# begin main program
10191.9Sapb
10201.9Sapbparse_args ${1+"$@"}
10211.9Sapbmake_PLIST
10221.9Sapbchoose_version_number
10231.9SapbSYSPKG_DB_SUBDIR="${SYSPKG_DB_TOPDIR}/${pkg}-${t}"
10241.9Sapbdo_register_syspkg
10251.9Sapbif [ -n "${binpkgdir}" ]; then
10261.9Sapb	binpkgfile="${binpkgdir}/${pkg}-${t}.tgz"
10271.9Sapb	do_create_syspkg_tgz
10281.5Sdyoungfi
10291.1Sagc
10301.9Sapbexit 0
1031