11.1Sagc#! /bin/sh
21.1Sagc#
31.26Suki# $NetBSD: regpkg,v 1.26 2023/02/11 04:16:57 uki Exp $
41.1Sagc#
51.17Sagc# Copyright (c) 2003,2009 The NetBSD Foundation, Inc.
61.17Sagc# All rights reserved.
71.17Sagc#
81.17Sagc# This code is derived from software contributed to The NetBSD Foundation
91.17Sagc# by Alistair Crooks (agc@NetBSD.org)
101.1Sagc#
111.1Sagc# Redistribution and use in source and binary forms, with or without
121.1Sagc# modification, are permitted provided that the following conditions
131.1Sagc# are met:
141.1Sagc# 1. Redistributions of source code must retain the above copyright
151.1Sagc#    notice, this list of conditions and the following disclaimer.
161.1Sagc# 2. Redistributions in binary form must reproduce the above copyright
171.1Sagc#    notice, this list of conditions and the following disclaimer in the
181.1Sagc#    documentation and/or other materials provided with the distribution.
191.17Sagc#
201.17Sagc# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
211.17Sagc# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
221.17Sagc# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
231.17Sagc# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
241.17Sagc# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
251.17Sagc# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
261.17Sagc# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
271.17Sagc# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
281.17Sagc# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
291.17Sagc# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
301.17Sagc# POSSIBILITY OF SUCH DAMAGE.
311.1Sagc#
321.1Sagc
331.9Sapb# Usage: regpkg [options] set pkgname
341.9Sapb#
351.9Sapb# Registers a syspkg in the database directory,
361.9Sapb# and optionally creates a binary package.
371.9Sapb#
381.9Sapb# Options:
391.9Sapb#   -q		Quiet.
401.9Sapb#   -v		Verbose.
411.9Sapb#   -f		Force.
421.9Sapb#   -m		Ignore errors from missing files.
431.9Sapb#   -u		Update.
441.9Sapb#   -c		Use cached information from ${BUILD_INFO_CACHE}.
451.9Sapb#   -d destdir	Sets DESTDIR.
461.9Sapb#   -t binpkgdir Create a binary package (in *.tgz format) in the
471.9Sapb#		specified directory.  Without this option, a binary
481.9Sapb#		package is not created.
491.9Sapb#   -M metalog	Use the specified metalog file to override file
501.9Sapb#		or directory attributes when creating a binary package.
511.9Sapb#   -N etcdir	Use the specified directory for passwd and group files.
521.9Sapb#
531.9Sapb# When -f is set:  If the desired syspkg already exists, it is overwritten.
541.9Sapb# When -u is set:  If the desired syspkg already exists, it might be
551.9Sapb#		overwritten or left alone, depending on whether it's older
561.9Sapb#		or newer than the files that belong to the syspkg.
571.9Sapb# When neither -u nor -f are set:  It's an error for the desired syspkg
581.9Sapb#		to already exist.
591.1Sagc
601.9Sapbprog="${0##*/}"
611.9Sapbtoppid=$$
621.8Sapbrundir="$(dirname "$0")" # ${0%/*} isn't good enough when there's no "/"
631.9Sapb. "${rundir}/sets.subr"
641.9Sapb
651.9Sapbbomb()
661.9Sapb{
671.9Sapb	#echo "${prog}: bomb: start, toppid=${toppid} \$\$=$$"
681.9Sapb	kill ${toppid}		# in case we were invoked from a subshell
691.9Sapb	#echo "${prog}: bomb: killed ${toppid}"
701.9Sapb	exit 1
711.9Sapb}
721.6Serh
731.9Sapb# A literal newline
741.9Sapbnl='
751.9Sapb'
761.9Sapb# A literal tab
771.9Sapbtab='	'
781.9Sapb
791.9Sapb# Prefixes for error messages, warnings, and important informational
801.9Sapb# messages.
811.9SapbERROR="${prog}: ERROR: "
821.9SapbWARNING="${prog}: WARNING: "
831.9SapbNOTE="${prog}: NOTE: "
841.9SapbERRWARN="${ERROR}"	# may be changed by "-f" (force) command line flag
851.9SapbERRWARNNOTE="${ERROR}"	# may be changed by "-u" (update) command line flag
861.1Sagc
871.9Sapb#
881.9Sapb# All temporary files will go in ${SCRATCH}, which will be deleted on
891.9Sapb# exit.
901.9Sapb#
911.14SapbSCRATCH="$(${MKTEMP} -d "/var/tmp/${0##*/}.XXXXXX")"
921.9Sapbif [ $? -ne 0 -o \! -d "${SCRATCH}" ]; then
931.10Sapb	echo >&2 "${prog}: Could not create scratch directory."
941.9Sapb	bomb
951.1Sagcfi
961.1Sagc
971.9Sapb#
981.9Sapb# cleanup() always deletes the SCRATCH directory, and might also
991.9Sapb# delete other files or directories.
1001.9Sapb#
1011.9Sapbes=0
1021.9Sapbcleanup_must_delete_binpkgfile=false
1031.9Sapbcleanup_must_delete_dbsubdir=false
1041.14Sapbcleanup()
1051.9Sapb{
1061.9Sapb	trap - 0
1071.9Sapb	#echo "${prog}: cleanup start"
1081.9Sapb	if ${cleanup_must_delete_binpkgfile:-false} && [ -e "${binpkgfile}" ]
1091.9Sapb	then
1101.9Sapb		echo >&2 "${prog}: deleting partially-created ${binpkgfile}"
1111.9Sapb		rm -f "${binpkgfile}"
1121.9Sapb	fi
1131.9Sapb	if ${cleanup_must_delete_dbsubdir:-false} \
1141.9Sapb	   && [ -e "${SYSPKG_DB_SUBDIR}" ]
1151.9Sapb	then
1161.9Sapb		echo >&2 "${prog}: deleting partially-created ${SYSPKG_DB_SUBDIR}"
1171.9Sapb		rm -rf "${SYSPKG_DB_SUBDIR}"
1181.9Sapb	fi
1191.9Sapb	rm -rf "${SCRATCH}"
1201.9Sapb	#echo "${prog}: cleanup done, exit ${es}"
1211.9Sapb	exit ${es}
1221.9Sapb}
1231.9Sapbtrap 'es=128; cleanup' 1 2 3 13 15	# HUP INT QUIT PIPE TERM
1241.9Sapbtrap 'es=$?; cleanup' 0 		# EXIT
1251.9Sapb
1261.9Sapb#
1271.9Sapb# Parse command line args.
1281.9Sapb#
1291.9Sapbverbose=false
1301.9Sapbverbosity=0
1311.9Sapbquiet=false
1321.9Sapbforce=false
1331.9Sapbupdate=false
1341.9Sapballowmissing=false
1351.9SapbDESTDIR="${DESTDIR}"
1361.9Sapbbinpkgdir=""
1371.9Sapbmetalog=""
1381.9Sapbetcdir=""
1391.9SapbSYSPKG_DB_TOPDIR=""
1401.9Sapbpkgset=""
1411.9Sapbpkg=""
1421.14Sapbparse_args()
1431.9Sapb{
1441.9Sapb	while [ $# -gt 2 ]; do
1451.9Sapb		case "$1" in
1461.14Sapb		-q)	quiet=true; verbose=false ;;
1471.14Sapb		-v)	verbose=true; quiet=false
1481.9Sapb			verbosity=$(( ${verbosity} + 1 ))
1491.9Sapb			;;
1501.9Sapb		-f)	force=true ;;
1511.9Sapb		-u)	update=true ;;
1521.9Sapb		-m)	allowmissing=true ;;
1531.9Sapb		-c)	# The -c option is ignored.  The BUILD_INFO_CACHE
1541.9Sapb			# environment variable is used instead.
1551.9Sapb			;;
1561.14Sapb		-d)	DESTDIR="$2"; shift ;;
1571.9Sapb		-d*)	DESTDIR="${1#-?}" ;;
1581.14Sapb		-t)	binpkgdir="$2"; shift ;;
1591.9Sapb		-t*)	binpkgdir="${1#-?}" ;;
1601.14Sapb		-M)	metalog="$2"; shift ;;
1611.9Sapb		-M*)	metalog="${1#-?}" ;;
1621.14Sapb		-N)	etcdir="$2"; shift ;;
1631.9Sapb		-N*)	etcdir="${1#-?}" ;;
1641.9Sapb		*)	break ;;
1651.9Sapb		esac
1661.9Sapb		shift
1671.9Sapb	done
1681.9Sapb	if ${force}; then
1691.9Sapb		ERRWARN="${WARNING}"
1701.9Sapb	else
1711.9Sapb		ERRWARN="${ERROR}"
1721.9Sapb	fi
1731.9Sapb	if ${update}; then
1741.9Sapb		ERRWARNNOTE="${NOTE}"
1751.9Sapb	else
1761.9Sapb		ERRWARNNOTE="${ERRWARN}"
1771.9Sapb	fi
1781.9Sapb	DESTDIR="${DESTDIR%/}" # delete trailing "/" if any
1791.9Sapb	if [ \! -n "${etcdir}" ]; then
1801.9Sapb		etcdir="${DESTDIR}/etc"
1811.9Sapb	fi
1821.9Sapb	if [ -n "${binpkgdir}" -a \! -d "${binpkgdir}" ]; then
1831.9Sapb		echo >&2 "${ERROR}binary pkg directory ${binpkgdir} does not exist"
1841.9Sapb		bomb
1851.9Sapb	fi
1861.9Sapb	#
1871.9Sapb	# SYSPKG_DB_TOPDIR is the top level directory for registering
1881.9Sapb	# syspkgs.  It defaults to ${DESTDIR}/var/db/syspkg, but can be
1891.9Sapb	# overridden by environment variables SYSPKG_DBDIR or PKG_DBDIR.
1901.9Sapb	#
1911.9Sapb	# Note that this corresponds to the default value of PKG_DBDIR
1921.9Sapb	# set in .../distrib/syspkg/mk/bsd.syspkg.mk.
1931.9Sapb	# 
1941.9Sapb	SYSPKG_DB_TOPDIR="${SYSPKG_DBDIR:-${PKG_DBDIR:-${DESTDIR}/var/db/syspkg}}"
1951.9Sapb
1961.9Sapb	if [ $# -ne 2 ]; then
1971.9Sapb		echo "Usage: regpkg [options] set pkgname"
1981.9Sapb		bomb
1991.9Sapb	fi
2001.9Sapb
2011.9Sapb	pkgset="$1"
2021.9Sapb	pkg="$2"
2031.9Sapb}
2041.1Sagc
2051.9Sapb#
2061.9Sapb# make_PLIST() creates a skeleton PLIST from the pkgset description.
2071.9Sapb#
2081.9Sapb# The result is stored in the file ${PLIST}.
2091.9Sapb#
2101.9SapbPLIST="${SCRATCH}/PLIST"
2111.14Sapbmake_PLIST()
2121.9Sapb{
2131.14Sapb	if ${verbose}; then
2141.9Sapb		echo "Making PLIST for \"${pkg}\" package (part of ${pkgset} set)"
2151.9Sapb	fi
2161.9Sapb	prefix="${DESTDIR:-/}"
2171.9Sapb	realprefix=/
2181.9Sapb	${HOST_SH} "${rundir}/makeplist" -p "${prefix}" -I "${realprefix}" \
2191.9Sapb		"${pkgset}" "${pkg}" \
2201.9Sapb		>"${PLIST}" 2>"${SCRATCH}/makeplist-errors"
2211.14Sapb	if ${EGREP} -v '^DEBUG:' "${SCRATCH}/makeplist-errors"; then
2221.9Sapb		# "find" invoked from makeplist sometimes reports
2231.9Sapb		# errors about missing files or directories, and
2241.9Sapb		# makeplist ignores the errors.  Catch them here.
2251.9Sapb		echo >&2 "${ERROR}makeplist reported errors for ${pkg}:"
2261.9Sapb		cat >&2 "${SCRATCH}/makeplist-errors"
2271.9Sapb		echo >&2 "${ERROR}see above for errors from makeplist"
2281.9Sapb		if ${allowmissing}; then
2291.9Sapb			echo >&2 "${prog}: ${NOTE}: ignoring above errors, due to '-m' option."
2301.9Sapb		else
2311.9Sapb			${force} || bomb
2321.9Sapb		fi
2331.9Sapb	fi
2341.9Sapb}
2351.1Sagc
2361.9Sapb#
2371.9Sapb# init_allfiles() converts the PLIST (which contains relative filenames)
2381.9Sapb# into a list of absolute filenames.  Directories are excluded from the
2391.9Sapb# result.
2401.9Sapb# 
2411.9Sapb# The result is stored in the variable ${allfiles}.
2421.9Sapb#
2431.9Sapballfiles=''
2441.14Sapbinit_allfiles()
2451.9Sapb{
2461.9Sapb	[ -f "${PLIST}" ] || make_PLIST
2471.14Sapb	allfiles="$(${AWK} '
2481.9Sapb		BEGIN { destdir = "'"${DESTDIR%/}"'" }
2491.9Sapb		/^@cwd/ { prefix = $2; next }
2501.25Suki		/^@pkgdir/ { next }
2511.14Sapb		{ printf("%s%s%s\n", destdir, prefix, $0) }' "${PLIST}")"
2521.9Sapb}
2531.1Sagc
2541.9Sapb#
2551.9Sapb# init_newestfile() finds the newest file (most recent mtime).
2561.9Sapb#
2571.9Sapb# The result is stored in the variable ${newestfile}.
2581.9Sapb#
2591.9Sapbnewestfile=''
2601.14Sapbinit_newestfile()
2611.9Sapb{
2621.9Sapb	[ -s "${allfiles}" ] || init_allfiles
2631.9Sapb	# We assume no shell special characters in ${allfiles},
2641.9Sapb	# and spaces only between file names, not inside file names.
2651.9Sapb	# This should be safe, because it has no no user-specified parts.
2661.14Sapb	newestfile="$(${LS} -1dt ${allfiles} | ${SED} '1q')"
2671.9Sapb}
2681.1Sagc
2691.9Sapb#
2701.9Sapb# Various ways of getting parts of the syspkg version number:
2711.9Sapb#
2721.9Sapb# get_osvers() - get the OS version number from osrelease.sh or $(uname -r),
2731.9Sapb#		return it in ${osvers}, and set ${method}.
2741.9Sapb# get_tinyvers() - get the tiny version number from the "versions" file,
2751.9Sapb#		and return it in ${tinyvers}.  Does not set ${method}.
2761.9Sapb# get_newest_rcsid_date() - get the newest RCS date,
2771.9Sapb#		and return it in ${newest}.  Does not set ${method}.
2781.9Sapb# get_newest_mtime_date() - get the newest file modification date,
2791.9Sapb#		and return it in ${newest}.  Does not set ${method}.
2801.9Sapb# get_newest_date() - get date from rcsid or mtime, return it in ${newest},
2811.9Sapb#		and set ${method}.
2821.9Sapb#
2831.14Sapbget_osvers()
2841.9Sapb{
2851.3Sagc	if [ -f ../../sys/conf/osrelease.sh ]; then
2861.8Sapb		osvers="$(${HOST_SH} ../../sys/conf/osrelease.sh)"
2871.4Sdyoung		method=osreleases
2881.3Sagc	else
2891.8Sapb		osvers="$(${UNAME} -r)"
2901.3Sagc		method=uname
2911.3Sagc	fi
2921.9Sapb	#echo "${osvers}"
2931.9Sapb}
2941.14Sapbget_tinyvers()
2951.9Sapb{
2961.14Sapb	tinyvers="$(${AWK} '$1 ~ '/"${pkg}"/' { print $2 }' \
2971.14Sapb			"${rundir}/versions")"
2981.9Sapb	case "${tinyvers}" in
2991.9Sapb	"")	tinyvers=0
3001.9Sapb		;;
3011.9Sapb	esac
3021.9Sapb	#echo "${tinyvers}"
3031.9Sapb}
3041.9Sapbget_newest_rcsid_date()
3051.9Sapb{
3061.9Sapb	[ -s "${allfiles}" ] || init_allfiles
3071.9Sapb
3081.9Sapb	# Old RCS identifiers might have 2-digit years, so we match both
3091.9Sapb	# YY/MM/DD and YYYY/MM/DD.  We also try to deal with the Y10K
3101.9Sapb	# problem by allowing >4 digit years.
3111.9Sapb	newest=0
3121.9Sapb	case "${allfiles}" in
3131.3Sagc	"")	;;
3141.14Sapb	*)	newest="$(${IDENT} ${allfiles} 2>/dev/null | ${AWK} '
3151.3Sagc			BEGIN { last = 0 }
3161.3Sagc			$2 == "crt0.c,v" { next }
3171.9Sapb			NF == 8 && \
3181.9Sapb			$4 ~ /^[0-9][0-9]\/[0-9][0-9]\/[0-9][0-9]$/ \
3191.9Sapb				{ t = "19" $4; gsub("/", "", t);
3201.9Sapb				  if (t > last) last = t; }
3211.9Sapb			NF == 8 && \
3221.9Sapb			$4 ~ /^[0-9][0-9][0-9][0-9][0-9]*\/[0-9][0-9]\/[0-9][0-9]$/ \
3231.9Sapb				{ t = $4; gsub("/", "", t);
3241.9Sapb				  if (t > last) last = t; }
3251.14Sapb			END { print last }')"
3261.3Sagc		method=ident
3271.3Sagc		;;
3281.3Sagc	esac
3291.9Sapb	#echo "${newest}"
3301.9Sapb}
3311.14Sapbget_newest_mtime_date()
3321.9Sapb{
3331.9Sapb	[ -s "${newestfile}" ] || init_newestfile
3341.9Sapb
3351.9Sapb	# We could simplify the awk program to take advantage of the
3361.9Sapb	# fact thet it should have exactly one line of input.
3371.14Sapb	newest="$(${ENV_CMD} TZ=UTC LOCALE=C ${LS} -lT "${newestfile}" \
3381.9Sapb		| ${AWK} '
3391.9Sapb		BEGIN { newest = 0 }
3401.9Sapb		{
3411.9Sapb			t = $9 "";
3421.9Sapb			if ($6 == "Jan") t = t "01";
3431.9Sapb			if ($6 == "Feb") t = t "02";
3441.9Sapb			if ($6 == "Mar") t = t "03";
3451.9Sapb			if ($6 == "Apr") t = t "04";
3461.9Sapb			if ($6 == "May") t = t "05";
3471.9Sapb			if ($6 == "Jun") t = t "06";
3481.9Sapb			if ($6 == "Jul") t = t "07";
3491.9Sapb			if ($6 == "Aug") t = t "08";
3501.9Sapb			if ($6 == "Sep") t = t "09";
3511.9Sapb			if ($6 == "Oct") t = t "10";
3521.9Sapb			if ($6 == "Nov") t = t "11";
3531.9Sapb			if ($6 == "Dec") t = t "12";
3541.9Sapb			if ($7 < 10) t = t "0";
3551.9Sapb			t = t $7;
3561.9Sapb			#these next two lines add the 24h clock onto the date
3571.9Sapb			#gsub(":", "", $8);
3581.9Sapb			#t = sprintf("%s.%4.4s", t, $8);
3591.9Sapb			if (t > newest) newest = t;
3601.9Sapb		}
3611.14Sapb		END { print newest }')"
3621.9Sapb	#echo "${newest}"
3631.9Sapb}
3641.14Sapbget_newest_date()
3651.9Sapb{
3661.9Sapb	get_newest_rcsid_date
3671.9Sapb	case "${newest}" in
3681.9Sapb	""|0)	get_newest_mtime_date
3691.3Sagc		method=ls
3701.3Sagc		;;
3711.9Sapb	*)	method=rcsid
3721.9Sapb		;;
3731.3Sagc	esac
3741.9Sapb	#echo "${newest}"
3751.9Sapb}
3761.9Sapb
3771.9Sapb#
3781.9Sapb# choose_version_number() chooses the syspkg version number,
3791.9Sapb# by concatenating several components (OS version, syspkg "tiny"
3801.9Sapb# version and date).  We end up with something like
3811.9Sapb# osvers="3.99.15", tinyvers="0", newest="20060104",
3821.9Sapb# and t="3.99.15.0.20060104".
3831.9Sapb#
3841.9Sapb# The result is stored in the variables ${t} and ${method}.
3851.9Sapb#
3861.9Sapbmethod=''
3871.9Sapbt=''
3881.14Sapbchoose_version_number()
3891.9Sapb{
3901.14Sapb	get_osvers; m1="${method}"
3911.9Sapb	get_tinyvers # does not set ${method}
3921.14Sapb	get_newest_date; m2="${method}"
3931.9Sapb	t="${osvers}.${tinyvers}.${newest}"
3941.9Sapb	method="${m1}.${m2}"
3951.9Sapb
3961.9Sapb	# print version number that we're using
3971.9Sapb	if ${verbose}; then
3981.9Sapb		echo "${pkg} - ${t} version using ${method} method"
3991.9Sapb	fi
4001.9Sapb}
4011.9Sapb
4021.9Sapb#
4031.13Sapb# init_db_opts() sets the dbfile, dbtype and db_opts variables,
4041.13Sapb# used for accessing the pkgdb.byfile.db database.
4051.13Sapb#
4061.14Sapbinit_db_opts()
4071.13Sapb{
4081.13Sapb	dbfile="${SYSPKG_DB_TOPDIR}/pkgdb.byfile.db"
4091.13Sapb	dbtype="btree"
4101.13Sapb	db_opts=''
4111.14Sapb	: ${TARGET_ENDIANNESS:="$(arch_to_endian "${MACHINE_ARCH}")"}
4121.13Sapb	case "${TARGET_ENDIANNESS}" in
4131.13Sapb	4321)	db_opts="${db_opts} -E B" # big-endian
4141.13Sapb		;;
4151.13Sapb	1234)	db_opts="${db_opts} -E L" # little-endian
4161.13Sapb		;;
4171.13Sapb	*)
4181.13Sapb		echo >&2 "${WARNING}Unknown or unsupported target endianness"
4191.13Sapb		echo >&2 "${NOTE}Using host endianness"
4201.13Sapb		;;
4211.13Sapb	esac
4221.14Sapb	if ${update} || ${force}; then
4231.13Sapb		# overwriting an existing entry is not an error
4241.13Sapb		db_opts="${db_opts} -R"
4251.13Sapb	fi
4261.13Sapb	if [ ${verbosity} -lt 2 ]; then
4271.13Sapb		# don't print all the keys added to the database
4281.13Sapb		db_opts="${db_opts} -q"
4291.13Sapb	fi
4301.13Sapb}
4311.13Sapb
4321.13Sapb#
4331.9Sapb# print_dir_exec_lines outputs an "@exec install" line for each
4341.9Sapb# directory in ${PLIST}
4351.9Sapb#
4361.14Sapbprint_dir_exec_lines()
4371.9Sapb{
4381.9Sapb	local dir uname gname mode
4391.9Sapb	local dot_slash_dir
4401.9Sapb	local no_dot_dir
4411.9Sapb	local word line
4421.25Suki	${AWK} '/^@pkgdir/ { print $2 }' <"${PLIST}" | \
4431.9Sapb	${SORT} | \
4441.14Sapb	while read dir; do
4451.9Sapb		# Sanitise the name. ${dir} could be an absolute or
4461.9Sapb		# relative name, with or without a leading "./".
4471.9Sapb		# ${dot_slash_dir} always has a leading "./" (except when
4481.9Sapb		# it's exactly equal to "."). ${no_dot_dir} never has a
4491.9Sapb		# leading "." or "/" (except when it's exactly equal to
4501.9Sapb		# ".").
4511.9Sapb		case "${dir}" in
4521.9Sapb		.|./|/)	dot_slash_dir=.  ;;
4531.9Sapb		./*)	dot_slash_dir="${dir}" ;;
4541.9Sapb		/*)	dot_slash_dir=".${dir}" ;;
4551.9Sapb		*)	dot_slash_dir="./${dir}" ;;
4561.9Sapb		esac
4571.9Sapb		no_dot_dir="${dot_slash_dir#./}"
4581.9Sapb		# Get the directory's owner, group, and mode
4591.9Sapb		# from the live file system, or let it be overridden
4601.9Sapb		# by the metalog.
4611.14Sapb		eval "$(${STAT} -f 'uname=%Su gname=%Sg mode=%#OLp' \
4621.14Sapb				"${DESTDIR}/${dot_slash_dir}")"
4631.9Sapb		if [ -n "${metalog}" ]; then
4641.14Sapb			line="$(echo "${dot_slash_dir}" | \
4651.9Sapb				${AWK} -f "${rundir}/join.awk" \
4661.14Sapb					/dev/stdin "${metalog}")"
4671.14Sapb			for word in ${line}; do
4681.9Sapb				case "${word}" in
4691.9Sapb				uname=*|gname=*|mode=*)	eval "${word}" ;;
4701.9Sapb				esac
4711.9Sapb			done
4721.9Sapb		fi
4731.9Sapb		# XXX: Work around yet another pkg_add bug: @cwd lines
4741.9Sapb		# do not actually cause the working directory to change,
4751.9Sapb		# so file names in @exec lines need to be qualified by
4761.9Sapb		# %D, which (in our case, since we know there's an
4771.9Sapb		# "@cwd /" line) will be the dir name passed to
4781.9Sapb		# "pkg_add -p PREFIX".
4791.9Sapb		case "${no_dot_dir}" in
4801.9Sapb		.) d="%D" ;;
4811.9Sapb		*) d="%D/${no_dot_dir}" ;;
4821.9Sapb		esac
4831.9Sapb		cat <<EOF
4841.9Sapb@exec install -d -o ${uname} -g ${gname} -m ${mode} ${d}
4851.9SapbEOF
4861.9Sapb	done
4871.9Sapb}
4881.2Sjwise
4891.9Sapb#
4901.9Sapb# register_syspkg() registers the syspkg in ${SYSPKG_DB_TOPDIR}.
4911.9Sapb# This involves creating the subdirectory ${SYSPKG_DB_SUBDIR}
4921.9Sapb# and populating it with several files.
4931.9Sapb#
4941.14Sapbregister_syspkg()
4951.9Sapb{
4961.9Sapb	cleanup_must_delete_dbsubdir=true
4971.9Sapb	[ -n "${SYSPKG_DB_SUBDIR}" ] || bomb
4981.9Sapb	mkdir -p "${SYSPKG_DB_SUBDIR}"
4991.9Sapb
5001.9Sapb	#
5011.9Sapb	# Guess what versions of other packages to depend on.
5021.9Sapb	#
5031.9Sapb	# If we are using the OS version as part of the pkg
5041.9Sapb	# version, then depend on any version ">=${osvers}".  For
5051.9Sapb	# example, etc-sys-etc-1.6ZI.0.20040206 might depend on
5061.9Sapb	# base-sys-root>=1.6ZI.
5071.9Sapb	#
5081.9Sapb	# Failing that, depend on any version "-[0-9]*".
5091.9Sapb	#
5101.9Sapb	# XXX: We could extend the format of the "deps" file to carry
5111.9Sapb	# this sort of information, so we wouldn't have to guess.
5121.9Sapb	#
5131.9Sapb	case "${t}" in
5141.9Sapb	${osvers}.*)	depversion=">=${osvers}" ;;
5151.9Sapb	*)		depversion="-[0-9]*" ;;
5161.9Sapb	esac
5171.9Sapb
5181.9Sapb	#
5191.9Sapb	# Add the dependencies.
5201.9Sapb	#
5211.9Sapb	# We always add a "@pkgdep" line for each prerequisite package.
5221.9Sapb	#
5231.9Sapb	# If the prerequisite pkg is already registered (as it should be
5241.9Sapb	# if our caller is doing things in the right order), then we put
5251.9Sapb	# its exact version number in a "@blddep" line.
5261.9Sapb	#
5271.9Sapb	${AWK} '$1 ~ '/"${pkg}"/' { print $2 }' "${rundir}/deps" | ${SORT} | \
5281.14Sapb	while read depname; do
5291.9Sapb		# ${pkgdepglob} is a shell glob pattern that should match
5301.9Sapb		# any version of a pkg.  ${pkgdep} uses the special syntax
5311.9Sapb		# for pkg dependencies, and is not usable as a shell
5321.9Sapb		# glob pattern.
5331.9Sapb		pkgdepglob="${depname}-[0-9]*"
5341.9Sapb		pkgdep="${depname}${depversion}"
5351.9Sapb		echo "@pkgdep ${pkgdep}"
5361.14Sapb		blddep="$(cd "${SYSPKG_DB_TOPDIR}" && echo ${pkgdepglob} \
5371.14Sapb			|| bomb)"
5381.9Sapb		case "${blddep}" in
5391.9Sapb		*\*)	# pkgdepglob did not match anything
5401.9Sapb			echo >&2 "${WARNING}${pkg} depends on '${pkgdep}' but there is no matching syspkg in ${SYSPKG_DB_TOPDIR}"
5411.9Sapb			;;
5421.9Sapb		*\ *)	# pkgdepglob matched more than once.
5431.9Sapb			echo >&2 "${ERRWARN}${pkg} depends on '${pkgdep}' but there are multiple matching syspkgs in ${SYSPKG_DB_TOPDIR}"
5441.9Sapb			${force} || bomb
5451.9Sapb			# If ${force} is set, then assume that the last
5461.9Sapb			# match is the most recent.
5471.9Sapb			# XXX: This might be wrong, because of
5481.9Sapb			# differences between lexical sorting and
5491.9Sapb			# numeric sorting.
5501.9Sapb			lastmatch="${blddep##* }"
5511.9Sapb			echo "@blddep ${lastmatch}"
5521.9Sapb			;;
5531.9Sapb		*)	# exactly one match.
5541.9Sapb			# XXX: We ignore the possibility that the
5551.9Sapb			# version we found via ${pkgdepglob} might not
5561.9Sapb			# satisfy ${pkgdep}.  We could conceivably use
5571.9Sapb			# "pkg_admin pmatch" to check, but that's not a
5581.9Sapb			# host tool so we can't assume that it will be
5591.9Sapb			# available.
5601.9Sapb			echo "@blddep ${blddep}"
5611.9Sapb			;;
5621.9Sapb		esac
5631.9Sapb	done >>"${PLIST}"
5641.9Sapb
5651.9Sapb	# create the comment (should be one line)
5661.14Sapb	comment="$(${AWK} '$1 ~ '/"${pkg}"/' \
5671.9Sapb			{ print substr($0, length($1) + 2) }' \
5681.14Sapb			"${rundir}/comments")"
5691.9Sapb	case "${comment}" in
5701.9Sapb	"")	echo >&2 "${WARNING}no comment for \"${pkg}\" (using placeholder)"
5711.9Sapb		comment="System package for ${pkg}"
5721.9Sapb		;;
5731.9Sapb	*"${nl}"*)
5741.9Sapb		echo >&2 "${ERRWARN}multi-line comment for \"${pkg}\""
5751.9Sapb		${force} || bomb
5761.9Sapb		;;
5771.9Sapb	esac
5781.9Sapb	echo "${comment}" > "${SYSPKG_DB_SUBDIR}/+COMMENT"
5791.1Sagc
5801.9Sapb	# create the description (could be multiple lines)
5811.14Sapb	descr="$(${AWK} '$1 ~ '/"${pkg}"/' {
5821.9Sapb			print substr($0, length($1) + 2) }' \
5831.14Sapb			"${rundir}/descrs")"
5841.9Sapb	case "${descr}" in
5851.9Sapb	"")	echo >&2 "${WARNING}no description for \"${pkg}\" (re-using comment)" 2>&1
5861.9Sapb		descr="${comment}"
5871.9Sapb		;;
5881.9Sapb	esac
5891.9Sapb	echo "${descr}" > "${SYSPKG_DB_SUBDIR}/+DESC"
5901.9Sapb	${PRINTF} "\nHomepage:\nhttp://www.NetBSD.org/\n" >> "${SYSPKG_DB_SUBDIR}/+DESC"
5911.1Sagc
5921.9Sapb	# create the build information
5931.9Sapb	if [ x"${BUILD_INFO_CACHE}" = x ]; then
5941.9Sapb		{
5951.9Sapb		# These variables describe the build
5961.9Sapb		# environment, not the target.
5971.9Sapb		echo "OPSYS=$(${UNAME} -s)"
5981.9Sapb		echo "OS_VERSION=$(${UNAME} -r)"
5991.15Sapb		${MAKE} -B -f- all <<EOF
6001.4Sdyoung.include <bsd.own.mk>
6011.4Sdyoungall:
6021.4Sdyoung	@echo OBJECT_FMT=${OBJECT_FMT}
6031.4Sdyoung	@echo MACHINE_ARCH=${MACHINE_ARCH}
6041.4Sdyoung	@echo MACHINE_GNU_ARCH=${MACHINE_GNU_ARCH}
6051.4SdyoungEOF
6061.9Sapb		} > "${SYSPKG_DB_SUBDIR}/+BUILD_INFO"
6071.9Sapb	else
6081.9Sapb		cp "${BUILD_INFO_CACHE}" "${SYSPKG_DB_SUBDIR}/+BUILD_INFO"
6091.9Sapb	fi
6101.9Sapb
6111.9Sapb	# test for attributes
6121.9Sapb	args=""
6131.14Sapb	attrs="$(${AWK} '$1 ~ '/"${pkg}"/' { \
6141.9Sapb			print substr($0, length($1) + 2) }' \
6151.14Sapb		"${rundir}/attrs")"
6161.9Sapb	for a in "${attrs}"; do
6171.9Sapb		case "${attrs}" in
6181.9Sapb		"")	;;
6191.9Sapb		preserve)
6201.9Sapb			echo "${pkg}-${t}" >"${SYSPKG_DB_SUBDIR}/+PRESERVE"
6211.9Sapb			args="${args} -n ${SYSPKG_DB_SUBDIR}/+PRESERVE"
6221.9Sapb			;;
6231.9Sapb		esac
6241.9Sapb	done
6251.9Sapb
6261.9Sapb	#
6271.9Sapb	# Create ${SYSPKGSIR}/+CONTENTS from ${PLIST}, by adding an
6281.9Sapb	# "@name" line and a lot of "@comment MD5:" lines.
6291.9Sapb	#
6301.9Sapb	{
6311.26Suki		rcsid='$NetBSD: regpkg,v 1.26 2023/02/11 04:16:57 uki Exp $'
6321.14Sapb		utcdate="$(${ENV_CMD} TZ=UTC LOCALE=C \
6331.14Sapb			${DATE} '+%Y-%m-%d %H:%M')"
6341.9Sapb		user="${USER:-root}"
6351.19Sapb		host="$(${HOSTNAME_CMD})"
6361.9Sapb		echo "@name ${pkg}-${t}"
6371.9Sapb		echo "@comment Packaged at ${utcdate} UTC by ${user}@${host}"
6381.9Sapb		echo "@comment Packaged using ${prog} ${rcsid}"
6391.9Sapb		# XXX: "option extract-in-place" might help to get
6401.9Sapb		#	pkg_add to create directories.
6411.9Sapb		# XXX: no, it doesn't work.  Yet another pkg_add bug.
6421.9Sapb		## echo "@option extract-in-place"
6431.9Sapb		# Move the @pkgdep and @blddep lines up, so that
6441.9Sapb		# they are easy to see when people do "less
6451.9Sapb		# ${DESTDIR}/var/db/syspkg/*/+CONTENTS".
6461.9Sapb		${EGREP} '^(@pkgdep|@blddep)' "${PLIST}" || true
6471.9Sapb		# Now do the remainder of the file.
6481.14Sapb		while read line; do
6491.9Sapb			case "${line}" in
6501.9Sapb			@pkgdep*|@blddep*)
6511.9Sapb				# already handled by grep above
6521.9Sapb				;;
6531.9Sapb			@cwd*)
6541.9Sapb				# There should be exactly one @cwd line.
6551.9Sapb				# Just after it, add an "@exec mkdir"
6561.9Sapb				# line for every directory.  This is to
6571.9Sapb				# work around a pkg-add bug (see
6581.9Sapb				# <http://mail-index.NetBSD.org/tech-pkg/2003/12/11/0018.html>)
6591.9Sapb				echo "${line}"
6601.9Sapb				print_dir_exec_lines
6611.9Sapb				;;
6621.9Sapb			@*)	
6631.9Sapb				# just pass through all other @foo lines
6641.9Sapb				echo "${line}"
6651.9Sapb				;;
6661.9Sapb			*)	
6671.9Sapb				# This should be a file name.  Pass it
6681.26Suki				# through, and append "@comment SHA256:".
6691.9Sapb				echo "${line}"
6701.26Suki				file="${DESTDIR}/${line}"
6711.26Suki				if [ -f "${file}" ] && [ -r "${file}" ];
6721.9Sapb				then
6731.26Suki					sha256sum="$(${CKSUM} -a sha256 -n "${file}" \
6741.9Sapb						   | ${AWK} '{print $1}'
6751.9Sapb						)"
6761.26Suki					echo "@comment SHA256:${sha256sum}"
6771.9Sapb				fi
6781.9Sapb				;;
6791.9Sapb			esac
6801.9Sapb		done <"${PLIST}"
6811.9Sapb	} >"${SYSPKG_DB_SUBDIR}/+CONTENTS"
6821.9Sapb
6831.9Sapb	#
6841.9Sapb	#  Update ${SYSPKG_DB_TOPDIR}/pkgdb.byfile.db.
6851.9Sapb	#
6861.9Sapb	{
6871.13Sapb		init_db_opts # sets dbfile, dbtype, and db_opts
6881.9Sapb
6891.9Sapb		# Transform ${PLIST} into a form to be used as keys in
6901.9Sapb		# ${dbfile}.  The results look like absolute paths,
6911.9Sapb		# but they are really relative to ${DESTDIR}.
6921.9Sapb		#
6931.25Suki		# "@pkgdir ."		-> "/"
6941.25Suki		# "@pkgdir foo/bar"	-> "/foo/bar"
6951.25Suki		# "@pkgdir ./foo/bar"	-> "/foo/bar"
6961.9Sapb		# "foo/bar/baz"		-> "/foo/bar/baz"
6971.9Sapb		# "./foo/bar/baz"	-> "/foo/bar/baz"
6981.9Sapb		#
6991.9Sapb		dblist="${SCRATCH}/dblist"
7001.25Suki		${AWK} '/^@pkgdir \.\//	{gsub("^.", "", $2); print $2; next}
7011.25Suki			/^@pkgdir \.$/	{print "/"; next}
7021.25Suki			/^@pkgdir/	{print "/" $2; next}
7031.9Sapb			/^@/		{next}
7041.9Sapb			/^\.\//		{gsub("^.", "", $0); print $0; next}
7051.9Sapb			/./		{print "/" $0; next}' \
7061.9Sapb			<"${PLIST}" >"${dblist}"
7071.9Sapb		# Add all the path names to the database.
7081.9Sapb		${AWK} '{print $1 "\t" "'"${pkg}-${t}"'"}' <"${dblist}" \
7091.9Sapb		| ${DB} -w ${db_opts} -F "${tab}" -f - "${dbtype}" "${dbfile}"
7101.9Sapb	}
7111.9Sapb
7121.14Sapb	if ${verbose}; then
7131.9Sapb		echo "Registered ${pkg}-${t} in ${SYSPKG_DB_TOPDIR}"
7141.14Sapb	elif ! ${quiet}; then
7151.9Sapb		echo "Registered ${pkg}-${t}"
7161.9Sapb	fi
7171.9Sapb
7181.9Sapb	cleanup_must_delete_dbsubdir=false
7191.9Sapb}
7201.9Sapb
7211.9Sapb#
7221.9Sapb# create_syspkg_tgz() creates the *.tgz file for the package.
7231.9Sapb#
7241.9Sapb# The output file is ${binpkgdir}/${pkg}-${t}.tgz.
7251.9Sapb#
7261.14Sapbcreate_syspkg_tgz()
7271.9Sapb{
7281.9Sapb	#
7291.9Sapb	# pkg_create does not understand metalog files, so we have to
7301.9Sapb	# use pax directly.
7311.9Sapb	#
7321.9Sapb	# We create two specfiles: specfile_overhead describes the
7331.9Sapb	# special files that are part of the package system's metadata
7341.9Sapb	# (+CONTENTS, +COMMENT, +DESCR, and more); and specfile_payload
7351.9Sapb	# describes the files and directories that we actually want as
7361.9Sapb	# part of the package's payload.
7371.9Sapb	#
7381.9Sapb	# We then use the specfiles to create a compressed tarball that
7391.9Sapb	# contains both the overhead files and the payload files.
7401.9Sapb	#
7411.9Sapb	# There's no trivial way to get a single pax run to do
7421.9Sapb	# everything we want, so we run pax twice, with a different
7431.9Sapb	# working directory and a different specfile each time.
7441.9Sapb	#
7451.9Sapb	# We could conceivably make clever use of pax's "-s" option to
7461.9Sapb	# get what we want from a single pax run with a single (more
7471.9Sapb	# complicated) specfile, but the extra trouble doesn't seem
7481.9Sapb	# warranted.
7491.9Sapb	#
7501.9Sapb	cleanup_must_delete_binpkgfile=true
7511.9Sapb	specfile_overhead="${SCRATCH}/spec_overhead"
7521.9Sapb	specfile_payload="${SCRATCH}/spec_payload"
7531.9Sapb	tarball_uncompressed="${SCRATCH}/tarball_uncompressed"
7541.9Sapb
7551.9Sapb	# Create a specfile for all the overhead files (+CONTENTS and
7561.9Sapb	# friends).
7571.9Sapb	{
7581.9Sapb		plusnames_first="${SCRATCH}/plusnames_first"
7591.9Sapb		plusnames_rest="${SCRATCH}/plusnames_rest"
7601.9Sapb
7611.9Sapb		# Ensure that the first few files are in the same order
7621.9Sapb		# that "pkg_create" would have used, just in case anything
7631.9Sapb		# depends on that.  Other files in alphabetical order.
7641.9Sapb		SHOULD_BE_FIRST="+CONTENTS +COMMENT +DESC"
7651.9Sapb		(
7661.9Sapb			cd "${SYSPKG_DB_SUBDIR}" || bomb
7671.9Sapb			for file in ${SHOULD_BE_FIRST}; do
7681.9Sapb				[ -e "./${file}" ] && echo "${file}"
7691.9Sapb			done >"${plusnames_first}"
7701.9Sapb			${LS} -1 | ${FGREP} -v -f "${plusnames_first}" \
7711.9Sapb				>"${plusnames_rest}" \
7721.9Sapb				|| true
7731.9Sapb		)
7741.9Sapb
7751.9Sapb		# Convert the file list to specfile format, and override the
7761.9Sapb		# uid/gid/mode.
7771.9Sapb		{
7781.9Sapb			echo ". optional type=dir"
7791.9Sapb			${AWK} '{print "./" $0 " type=file uid=0 gid=0 mode=0444"
7801.9Sapb				}' "${plusnames_first}" "${plusnames_rest}"
7811.9Sapb		} >"${specfile_overhead}"
7821.9Sapb	}
7831.9Sapb
7841.9Sapb	# Create a specfile for the payload of the package.
7851.9Sapb	{
7861.9Sapb		spec1="${SCRATCH}/spec1"
7871.9Sapb		spec2="${SCRATCH}/spec2"
7881.9Sapb
7891.9Sapb		# Transform ${PLIST} into simple specfile format:
7901.9Sapb		#
7911.25Suki		# "@pkgdir ."		-> ". type=dir"
7921.25Suki		# "@pkgdir foo/bar"	-> "./foo/bar type=dir"
7931.25Suki		# "@pkgdir ./foo/bar"	-> "./foo/bar type=dir"
7941.9Sapb		# "foo/bar/baz"		-> "./foo/bar/baz"
7951.9Sapb		# "./foo/bar/baz"	-> "./foo/bar/baz"
7961.9Sapb		#
7971.9Sapb		# Ignores @cwd lines.  This should be safe, given how
7981.9Sapb		# makeplist works.
7991.25Suki		${AWK} '/^@pkgdir \.\//	{print $2 " type=dir"; next}
8001.25Suki			/^@pkgdir \.$/	{print ". type=dir"; next}
8011.25Suki			/^@pkgdir/	{print "./" $2 " type=dir"; next}
8021.9Sapb			/^@/		{next}
8031.9Sapb			/^\.\//		{print $0; next}
8041.9Sapb			/./		{print "./" $0; next}' \
8051.21Suebayasi			<"${PLIST}" |
8061.21Suebayasi		# Escape some characters to match the new mtree(8) format.
8071.21Suebayasi		# C.f. usr.sbin/mtree/spec.c:vispath()
8081.21Suebayasi		# XXX escape only '[' for now
8091.22Suebayasi		${SED} -e 's,\[,\\133,g' \
8101.21Suebayasi		>"${spec1}"
8111.9Sapb
8121.9Sapb		# If metalog was specified, attributes from metalog override
8131.9Sapb		# attributes in the file system.  We also fake up an
8141.9Sapb		# entry for the ./etc/mtree/set.${pkgset} file.
8151.9Sapb		{
8161.9Sapb			if [ -n "${metalog}" ]; then
8171.9Sapb				${AWK} -f "${rundir}/join.awk" \
8181.9Sapb					"${spec1}" "${metalog}"
8191.9Sapb				${AWK} -f "${rundir}/join.awk" \
8201.9Sapb					"${spec1}" /dev/stdin <<EOF
8211.9Sapb./etc/mtree/set.${pkgset} type=file mode=0444 uname=root gname=wheel
8221.9SapbEOF
8231.9Sapb			else
8241.9Sapb				cat "${spec1}"
8251.9Sapb			fi
8261.9Sapb		} >"${spec2}"
8271.9Sapb
8281.9Sapb		#
8291.9Sapb		# If a file or directory to was mentioned explicitly
8301.9Sapb		# in ${PLIST} but not mentioned in ${metalog}, then the
8311.9Sapb		# file or directory will not be mentioned in ${spec2}.
8321.9Sapb		# This is an error, and means that the metalog was
8331.9Sapb		# not built correctly.
8341.9Sapb		#
8351.9Sapb		if [ -n "${metalog}" ]; then
8361.9Sapb			names1="${SCRATCH}/names1"
8371.9Sapb			names2="${SCRATCH}/names2"
8381.24Srhialto			${AWK} '{print $1}' <"${spec1}" | ${SORT} >"${names1}"
8391.24Srhialto			${AWK} '{print $1}' <"${spec2}" | ${SORT} >"${names2}"
8401.9Sapb			if ${FGREP} -v -f "${names2}" "${spec1}" >/dev/null
8411.9Sapb			then
8421.9Sapb				cat >&2 <<EOM
8431.9Sapb${ERRWARN}The metalog file (${metalog}) does not
8441.9Sapb	contain entries for the following files or directories
8451.9Sapb	which should be part of the ${pkg} syspkg:
8461.9SapbEOM
8471.9Sapb				${FGREP} -v -f "${names2}" "${spec1}" >&2
8481.9Sapb				${force} || bomb
8491.9Sapb			fi
8501.9Sapb			if ${FGREP} -v -f "${names1}" "${spec2}" >/dev/null
8511.9Sapb			then
8521.9Sapb				cat >&2 <<EOM
8531.9Sapb${ERRWARN}The following lines are in the metalog file
8541.9Sapb	(${metalog}), and the corresponding files or directories
8551.9Sapb	should be in the ${pkg} syspkg, but something is wrong:
8561.9SapbEOM
8571.9Sapb				${FGREP} -v -f "${names1}" "${spec2}" >&2
8581.9Sapb				bomb
8591.9Sapb			fi
8601.9Sapb		fi
8611.9Sapb
8621.9Sapb		# Add lines (tagged "optional") for any implicit directories.
8631.9Sapb		#
8641.9Sapb		# For example, if we have a file ./foo/bar/baz, then we add
8651.9Sapb		# "./foo/bar optional type=dir", "./foo optional type=dir",
8661.9Sapb		# and ". optional type=dir", unless those directories were
8671.9Sapb		# already mentioned explicitly.
8681.9Sapb		#
8691.9Sapb		${AWK} -f "${rundir}/getdirs.awk" "${spec2}" \
8701.9Sapb		| ${SORT} -u >"${specfile_payload}"
8711.9Sapb	}
8721.9Sapb
8731.9Sapb	# Use two pax invocations followed by gzip to create
8741.9Sapb	# the tgz file.
8751.9Sapb	#
8761.9Sapb	# Remove any leading "./" from path names, because that
8771.9Sapb	# could confuse tools that work with binary packages.
8781.9Sapb	(
8791.9Sapb		cd "${SYSPKG_DB_SUBDIR}" && \
8801.9Sapb		${PAX} -O -w -d -N"${etcdir}" -M '-s,^\./,,' \
8811.9Sapb			-f "${tarball_uncompressed}" \
8821.9Sapb			<"${specfile_overhead}" \
8831.9Sapb		|| bomb
8841.9Sapb	)
8851.9Sapb	(
8861.9Sapb		cd "${DESTDIR:-/}" && \
8871.9Sapb		${PAX} -O -w -d -N"${etcdir}" -M '-s,^\./,,' \
8881.9Sapb			-a -f "${tarball_uncompressed}" \
8891.9Sapb			<"${specfile_payload}" \
8901.9Sapb		|| bomb
8911.9Sapb	)
8921.16Sperry	${GZIP_CMD} -9n <"${tarball_uncompressed}" >"${binpkgfile}" || bomb
8931.9Sapb
8941.9Sapb	# (Extra space is to make message line up with "Registered" message.)
8951.14Sapb	if ${verbose}; then
8961.9Sapb		echo "  Packaged ${binpkgfile}"
8971.14Sapb	elif ! ${quiet}; then
8981.9Sapb		echo "  Packaged ${binpkgfile##*/}"
8991.9Sapb	fi
9001.9Sapb
9011.9Sapb	cleanup_must_delete_binpkgfile=false
9021.9Sapb
9031.9Sapb}
9041.9Sapb
9051.9Sapb#
9061.9Sapb# do_register_syspkg() registers the syspkg if appropriate.
9071.9Sapb#
9081.9Sapb# If SYSPKG_DB_SUBDIR already exists, that might be an error, depending
9091.9Sapb# on ${force} and ${update} flags.
9101.9Sapb#
9111.14Sapbdo_register_syspkg()
9121.9Sapb{
9131.9Sapb	# Check that necessary variables are defined
9141.9Sapb	[ -n "${SYSPKG_DB_TOPDIR}" ] || bomb
9151.9Sapb	[ -n "${SYSPKG_DB_SUBDIR}" ] || bomb
9161.9Sapb
9171.9Sapb	# Create SYSPKG_DB_TOPDIR if necessary
9181.9Sapb	[ -d "${SYSPKG_DB_TOPDIR}" ] || mkdir -p "${SYSPKG_DB_TOPDIR}" || bomb
9191.9Sapb
9201.13Sapb	# A function to delete db entries referring to any version of ${pkg}
9211.14Sapb	delete_old_db_entries()
9221.13Sapb	{
9231.13Sapb		init_db_opts # sets dbfile, dbtype, and db_opts
9241.13Sapb		dblist="${SCRATCH}/dblist"
9251.13Sapb		${DB} ${db_opts} -O "${tab}" "${dbtype}" "${dbfile}" \
9261.13Sapb		| ${AWK} -F "${tab}" '$2 ~ /^'"${pkg}"'-[0-9]/ { print $1 }' \
9271.13Sapb			>"${dblist}"
9281.13Sapb		${DB} -d ${db_opts} -f "${dblist}" "${dbtype}" "${dbfile}"
9291.13Sapb	}
9301.13Sapb
9311.13Sapb	# A function to delete any old version of ${pkg}
9321.14Sapb	delete_old_pkg()
9331.9Sapb	{
9341.13Sapb		pattern="${pkg}-[0-9]*"
9351.14Sapb		matches="$(cd "${SYSPKG_DB_TOPDIR}" && echo ${pattern} \
9361.14Sapb			|| bomb)"
9371.13Sapb		echo >&2 "${NOTE}deleting old pkg (${matches})"
9381.9Sapb		cleanup_must_delete_dbsubdir=true
9391.13Sapb		delete_old_db_entries
9401.13Sapb		( cd "${SYSPKG_DB_TOPDIR}" && rm -rf ${matches} )
9411.9Sapb	}
9421.9Sapb
9431.9Sapb	# Check whether another version of ${pkg} is already registered.
9441.9Sapb	pattern="${pkg}-[0-9]*"
9451.14Sapb	matches="$(cd "${SYSPKG_DB_TOPDIR}" && echo ${pattern} || bomb)"
9461.9Sapb	case "${matches}" in
9471.9Sapb	*\*)		;;	# wildcard did not match anything
9481.9Sapb	"${pkg}-${t}")	;;	# exact match
9491.13Sapb	*)	echo >&2 "${ERRWARNNOTE}another version of ${pkg} is already registered"
9501.13Sapb		${verbose} && echo >&2 "	in ${SYSPKG_DB_TOPDIR}"
9511.13Sapb		${verbose} && echo >&2 "	(while registering ${pkg}-${t})"
9521.13Sapb		${force} || ${update} || bomb
9531.13Sapb		delete_old_pkg
9541.9Sapb		;;
9551.9Sapb	esac
9561.9Sapb
9571.9Sapb	# Check whether the desired version of ${pkg} is already registered,
9581.9Sapb	# and create it if appropriate.
9591.9Sapb	if [ -d "${SYSPKG_DB_SUBDIR}" ]; then
9601.9Sapb		echo >&2 "${ERRWARNNOTE}${pkg}-${t} is already registered"
9611.9Sapb		${verbose} && echo >&2 "	in ${SYSPKG_DB_TOPDIR}"
9621.9Sapb		if ${force}; then
9631.13Sapb			delete_old_pkg
9641.13Sapb			register_syspkg
9651.9Sapb		elif ${update}; then
9661.9Sapb			#
9671.9Sapb			# If all files in SYSPKG_DB_SUBDIR are newer
9681.9Sapb			# than all files in the pkg, then do nothing.
9691.9Sapb			# Else delete and re-register the pkg.
9701.9Sapb			#
9711.9Sapb			[ -n "${newestfile}" ] || init_newestfile
9721.9Sapb			if [ -n "${newestfile}" ]; then
9731.14Sapb				case "$(${FIND} "${SYSPKG_DB_SUBDIR}" -type f \
9741.14Sapb					! -newer "${newestfile}" -print)" \
9751.9Sapb				in
9761.9Sapb				"")	;;
9771.13Sapb				*)
9781.13Sapb					echo >&2 "${NOTE}some files are newer but pkg version is unchanged"
9791.13Sapb					delete_old_pkg
9801.13Sapb					register_syspkg
9811.13Sapb					;;
9821.9Sapb				esac
9831.9Sapb
9841.9Sapb			else
9851.9Sapb				# No files in the pkg?  (This could happen
9861.9Sapb				# if a pkg contains only directories.)
9871.13Sapb				# Do nothing (keep the already-registered pkg).
9881.19Sapb				:
9891.9Sapb			fi
9901.9Sapb		else
9911.9Sapb			bomb
9921.9Sapb		fi
9931.9Sapb	else
9941.9Sapb		register_syspkg
9951.9Sapb	fi
9961.9Sapb}
9971.9Sapb
9981.9Sapb#
9991.20Smbalmer# do_create_syspkg_tgz() creates the binary pkg (*.tgz) if
10001.9Sapb# appropriate.
10011.9Sapb#
10021.9Sapb# If binpkgfile already exists, that might be an error, depending on
10031.9Sapb# ${force} and ${update} flags.
10041.9Sapb#
10051.14Sapbdo_create_syspkg_tgz()
10061.9Sapb{
10071.9Sapb	[ -n "${binpkgfile}" ] || bomb
10081.9Sapb
10091.14Sapb	delete_and_recreate()
10101.9Sapb	{
10111.9Sapb		echo >&2 "${ERRWARNNOTE}deleting and re-creating ${pkg}-${t}.tgz"
10121.9Sapb		rm -f "${binpkgfile}"
10131.9Sapb		create_syspkg_tgz
10141.9Sapb	}
10151.9Sapb
10161.9Sapb	# Check whether another version of ${pkg} already exists.
10171.9Sapb	pattern="${pkg}-[0-9]*"
10181.14Sapb	matches="$(cd "${binpkgdir}" && echo ${pattern} || bomb)"
10191.9Sapb	case "${matches}" in
10201.9Sapb	*\*)	;;	# wildcard did not match anything
10211.9Sapb	"${pkg}-${t}.tgz") ;;	# exact match
10221.13Sapb	*)	echo >&2 "${ERRWARNNOTE}another version of ${pkg} binary pkg already exists"
10231.13Sapb		${verbose} && echo >&2 "	in ${binpkgdir}"
10241.13Sapb		${verbose} && echo >&2 "	(while creating ${pkg}-${t}.tgz)"
10251.13Sapb		# If neither force nor update, this is a fatal error.
10261.13Sapb		# If force but not update, then leave old .tgz in place.
10271.13Sapb		# If update, then delete the old .tgz.
10281.13Sapb		${force} || ${update} || bomb
10291.13Sapb		if ${update}; then
10301.13Sapb			echo >&2 "${NOTE}deleting old binary pkg (${matches})"
10311.13Sapb			( cd "${binpkgdir}" && rm -f ${matches} || bomb )
10321.13Sapb		fi
10331.9Sapb		;;
10341.9Sapb	esac
10351.9Sapb
10361.9Sapb	# Check whether the desired version of ${pkg} already exists,
10371.9Sapb	# and create it if appropriate.
10381.9Sapb	if [ -e "${binpkgfile}" ]; then
10391.9Sapb		echo >&2 "${ERRWARNNOTE}${pkg}-${t}.tgz already exists"
10401.9Sapb		${verbose} && echo >&2 "	in ${binpkgdir}"
10411.9Sapb		if ${force}; then
10421.9Sapb			delete_and_recreate
10431.9Sapb		elif ${update}; then
10441.9Sapb			#
10451.9Sapb			# If all files in SYSPKG_DB_SUBDIR are older
10461.9Sapb			# than ${binpkgfile}, then do nothing.
10471.9Sapb			# Else delete and re-create the tgz.
10481.9Sapb			#
10491.14Sapb			case "$(${FIND} "${SYSPKG_DB_SUBDIR}" -type f \
10501.14Sapb				-newer "${binpkgfile}" -print)" \
10511.9Sapb			in
10521.9Sapb			"")	;;
10531.9Sapb			*)	delete_and_recreate ;;
10541.9Sapb			esac
10551.9Sapb		else
10561.9Sapb			bomb
10571.9Sapb		fi
10581.9Sapb	else
10591.9Sapb		create_syspkg_tgz
10601.9Sapb	fi
10611.9Sapb}
10621.9Sapb
10631.9Sapb####################
10641.9Sapb# begin main program
10651.9Sapb
10661.9Sapbparse_args ${1+"$@"}
10671.9Sapbmake_PLIST
10681.9Sapbchoose_version_number
10691.9SapbSYSPKG_DB_SUBDIR="${SYSPKG_DB_TOPDIR}/${pkg}-${t}"
10701.9Sapbdo_register_syspkg
10711.9Sapbif [ -n "${binpkgdir}" ]; then
10721.9Sapb	binpkgfile="${binpkgdir}/${pkg}-${t}.tgz"
10731.9Sapb	do_create_syspkg_tgz
10741.5Sdyoungfi
10751.1Sagc
10761.9Sapbexit 0
1077