2022-05-31 16:02:44 -04:00
|
|
|
#!/bin/bash
|
|
|
|
#
|
|
|
|
# pkgmeek - a drop-in replacement for pkgmk
|
|
|
|
# based on upkgmk (c) 2018 therealfun
|
|
|
|
# and pkgmk (c) 2004--2022 Per Liden et al.
|
|
|
|
# Distributed under the same license,
|
|
|
|
# https://crux.nu/gitweb/?p=tools/pkgutils.git;a=blob_plain;f=COPYING;hb=HEAD
|
|
|
|
|
|
|
|
main() {
|
|
|
|
######################## main routine ################################
|
2022-06-01 11:33:35 -04:00
|
|
|
local o_ignored work _local_ here url u f errDL errUZ; local pkg_ood=1
|
2022-05-31 16:02:44 -04:00
|
|
|
parse_options "$@"
|
2022-06-01 10:55:07 -04:00
|
|
|
[ "$PKGMK_RECURSIVE" = "no" ] || recursive "$@"
|
2022-05-31 16:02:44 -04:00
|
|
|
#
|
|
|
|
# Exit early if cleaning was requested
|
|
|
|
#
|
|
|
|
if [ "$PKGMK_CLEAN" = "yes" ]; then
|
|
|
|
[ "$PKGMK_MTIME_ONLY" = "yes" ] && o_ignored="-utd"
|
|
|
|
[ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ] && o_ignored+=" -uf"
|
|
|
|
[ "$PKGMK_CHECK_SIG" = "yes" ] && o_ignored+=" -cs"
|
|
|
|
[ "$PKGMK_REFRESH_SIG" = "yes" ] && refresh_signature
|
|
|
|
[ "$o_ignored" = "" ] || { warning "option -c nullifies these requested options:";
|
2022-06-01 17:37:01 -04:00
|
|
|
info "$o_ignored"; }
|
2022-06-01 05:58:13 -04:00
|
|
|
exec $PRTWASH_COMMAND -p -s -q "$(pwd)"
|
2022-05-31 16:02:44 -04:00
|
|
|
fi
|
|
|
|
#
|
|
|
|
# Read the Pkgfile to determine what to do next. But first ensure that
|
|
|
|
# it came from a trusted source (FS#1851)
|
|
|
|
#
|
2022-06-01 08:31:21 -04:00
|
|
|
validate_pkgfile || exit $E_PKGFILE
|
2022-05-31 16:02:44 -04:00
|
|
|
[ -f .32bit ] && PGKMK_ARCH=32 || PKGMK_ARCH=64
|
|
|
|
. "Pkgfile"; . "$PKGMK_CONF"
|
|
|
|
|
|
|
|
set -e
|
|
|
|
|
2022-06-01 10:55:07 -04:00
|
|
|
# respect the settings for centralized source and package directories ...
|
2022-05-31 16:02:44 -04:00
|
|
|
[ -v pkg_dir ] || pkg_dir="$PKGMK_PACKAGE_DIR"/
|
|
|
|
[ -w "$pkg_dir" ] || pkg_dir="$(pwd)"/
|
|
|
|
[ -v src_dir ] || src_dir="$PKGMK_SOURCE_DIR"
|
|
|
|
[ -w "$src_dir" ] || src_dir=
|
|
|
|
|
2022-06-01 10:55:07 -04:00
|
|
|
# ... and for WORK_DIR in case the user wants to build in RAM
|
2022-05-31 16:02:44 -04:00
|
|
|
[ -v PKGMK_WORK_DIR ] && work="$PKGMK_WORK_DIR"
|
|
|
|
|
|
|
|
# Let the main routine and subsequent subroutines know what filenames
|
|
|
|
# they should expect to see on disk.
|
|
|
|
package="${name}#${version}-${release}.pkg.tar.${PKGMK_COMPRESSION_MODE}"
|
|
|
|
declare -A _local_
|
|
|
|
for (( s=0; s<${#source[@]}; s++ )); do
|
2022-06-01 19:45:19 -04:00
|
|
|
if [[ ${source[$s]} =~ ^(http|https|ssh|git)://.*/(.+)\.git ]]; then
|
2022-05-31 16:02:44 -04:00
|
|
|
_local_[$s]="${BASH_REMATCH[2]}"
|
|
|
|
elif [[ ${source[$s]} =~ ^(http|https|ftp|file)://.*/(.+) ]]; then
|
|
|
|
_local_[$s]="${BASH_REMATCH[2]}"
|
|
|
|
else
|
|
|
|
_local_[$s]="${source[$s]}"
|
|
|
|
fi
|
|
|
|
[ -z "${renames[$s]}" ] || [ "${renames[$s]}" = "SKIP" ] || \
|
|
|
|
_local_[$s]="${renames[$s]}"
|
|
|
|
done
|
|
|
|
# Example: _local_ = ( upstream-ball-v12.tgz
|
|
|
|
# random.patch
|
|
|
|
# some-git-repo/ )
|
|
|
|
|
|
|
|
# The effective user should at least have write permissions on $PWD
|
|
|
|
[ -w "$(dirname "$work")" ] || work="$(pwd)"/work
|
|
|
|
rm -rf "$work"; mkdir -p "$work"/{src,pkg} && cd "$work"
|
|
|
|
|
2022-06-01 05:58:13 -04:00
|
|
|
# Skip the retrieval of sources if the user only asked for '-utd'
|
2022-06-01 15:10:25 -04:00
|
|
|
errDL=0; [ "$PKGMK_MTIME_ONLY" = "yes" ] || {
|
|
|
|
for (( u=0; u<${#_local_[@]}; u++ )); do
|
|
|
|
here="${_local_[$u]}"; url="${source[$u]}";
|
2022-06-01 05:58:13 -04:00
|
|
|
# at least one of the following commands should put a file of the
|
|
|
|
# appropriate name in the current directory
|
2022-06-01 15:10:25 -04:00
|
|
|
[ -e "$here" ] || [ "$src_dir" = "" ] || [ ! -e "$src_dir/$here" ] || ln -sf "$src_dir/$here" ;
|
|
|
|
[ -e "$here" ] || [ ! -e "$PKGMK_ROOT/$here" ] || ln -sf "$PKGMK_ROOT/$here" . ;
|
|
|
|
[ -e "$here" ] || [[ $url =~ ^(https|ssh|git)://.*/(.+)\.git ]] || {
|
|
|
|
if "$PKGMK_DOWNLOAD_PROG" -O "$here" "$url"; then
|
|
|
|
[ "$src_dir" = "" ] || { mv "$here" "$src_dir"/ && ln -sf "$src_dir/$here" . ; };
|
|
|
|
fi; };
|
|
|
|
[ -e "$here" ] || [[ ! $url =~ ^(https|ssh|git)://.*/(.+)\.git ]] || \
|
|
|
|
( "$PKGMK_GIT_COMMAND" clone "$url" "$here" ) || continue ;
|
2022-06-01 06:27:29 -04:00
|
|
|
# but if not, exit with an informative error message
|
2022-06-01 15:10:25 -04:00
|
|
|
if [ ! -e "$here" ]; then
|
|
|
|
error "failed to download $here. Check connection and try again."
|
|
|
|
errDL+=1
|
|
|
|
fi ;
|
|
|
|
done ; }
|
2022-05-31 16:02:44 -04:00
|
|
|
|
2022-06-01 15:10:25 -04:00
|
|
|
[ "$errDL" != 0 ] || info "Successfully obtained all needed source files."
|
2022-06-01 10:55:07 -04:00
|
|
|
|
2022-06-01 05:58:13 -04:00
|
|
|
# If the user only asked for '-utd', perform the check using the sources that do exist.
|
2022-06-01 15:10:25 -04:00
|
|
|
check_pkg_mtime && pkg_ood=0 || pkg_ood=1
|
2022-05-31 16:02:44 -04:00
|
|
|
[ "$PKGMK_MTIME_ONLY" = "no" ] || exit $pkg_ood
|
2022-06-01 05:58:13 -04:00
|
|
|
|
2022-06-01 15:10:25 -04:00
|
|
|
[ "$PKGMK_DOWNLOAD_ONLY" = "no" ] || [ "$PKGMK_UPDATE_MD5" = "yes" ] || [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ] || [ "$PKGMK_UPDATE_SIG" = "yes" ] || [ "$PKGMK_EXTRACT_ONLY" = "yes" ] || [ "$errDL" = 0 ] || exit $(( E_DOWNLOAD*(errDL != 0) ))
|
2022-06-01 05:58:13 -04:00
|
|
|
|
|
|
|
# Some further tests before proceeding with the build
|
2022-06-01 17:37:01 -04:00
|
|
|
[ "$pkg_ood" = 1 ] || [ "$PKGMK_FORCE" = "yes" ] || [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ] \
|
|
|
|
|| [ "$PKGMK_UPDATE_SIG" = "yes" ] || [ "$PKGMK_UPDATE_MD5" = "yes" ] || [ "$PKGMK_EXTRACT_ONLY" = "no" ] \
|
|
|
|
|| { info "$package is up to date, use '-f' to force a rebuild."; exit 0; }
|
2022-06-01 11:39:39 -04:00
|
|
|
|
|
|
|
# Silence the progress report if the user never intended to proceed with unpacking
|
2022-05-31 16:02:44 -04:00
|
|
|
[ "$PKGMK_CHECK_SIG" = "yes" ] || echo "Checking signatures before unpacking..."
|
|
|
|
|
2022-06-01 05:58:13 -04:00
|
|
|
# The option -uf is meant to be used AFTER a previous invocation of pkgmeek has
|
|
|
|
# alerted the user to a footprint mismatch. The options -us|-um are likewise meant
|
|
|
|
# to update the signature|md5sum, which only requires the sources and the footprint.
|
2022-05-31 16:02:44 -04:00
|
|
|
if [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ]; then
|
|
|
|
[ -f "$package" ] || \
|
|
|
|
{ error "unable to update footprint. File '$package' not found.";
|
|
|
|
exit "$E_MANIFEST"; }
|
|
|
|
[ "$pkg_ood" = 0 ] || [ "$PKGMK_FORCE" = "yes" ] || \
|
|
|
|
{ error "outdated package. Use '-f' to force the footprint update.";
|
|
|
|
exit "$E_FOOTPRINT"; }
|
2022-06-01 05:58:13 -04:00
|
|
|
cat_manifest footprint > "$PKGMK_ROOT/.footprint" || \
|
2022-05-31 16:02:44 -04:00
|
|
|
{ error "Failed to write the footprint."; exit "$E_DIRPERM"; }
|
|
|
|
fi
|
2022-06-01 05:58:13 -04:00
|
|
|
[ "$PKGMK_UPDATE_SIG" = "no" ] || \
|
|
|
|
{ cat_signature > "$PKGMK_ROOT/.signature" &&
|
2022-06-01 08:31:21 -04:00
|
|
|
info "Signature successfully created."; } || \
|
2022-06-01 05:58:13 -04:00
|
|
|
{ cat_manifest md5sum > "$PKGMK_ROOT"/.md5sum &&
|
|
|
|
warning "Signature creation failed, falling back to md5sums."; } \
|
|
|
|
|| { info "Could not create signatures or md5sums."; exit "$E_DIRPERM"; }
|
|
|
|
[ "$PKGMK_UPDATE_MD5" = "no" ] || \
|
2022-06-01 08:31:21 -04:00
|
|
|
{ cat_manifest md5sum > "$PKGMK_ROOT"/.md5sum && info "md5sum updated."; } || \
|
2022-06-01 05:58:13 -04:00
|
|
|
{ info "Could not create requested md5sums."; exit "$E_DIRPERM"; }
|
2022-06-01 08:31:21 -04:00
|
|
|
|
2022-06-01 05:58:13 -04:00
|
|
|
# Exit after fulfilling any *explicit* requests for (signed) manifests
|
|
|
|
# (decision regarding the work directory is retained from the first run of pkgmeek)
|
|
|
|
if [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ] || [ "$PKGMK_UPDATE_SIG" = "yes" ] || \
|
|
|
|
[ "$PKGMK_UPDATE_MD5" = "yes" ];
|
2022-05-31 16:02:44 -04:00
|
|
|
then exit 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
# All the sources should be here by now, let's verify that we can trust them.
|
2022-06-01 05:58:13 -04:00
|
|
|
readonly cs_fail_msg="Use '--ignore-signature' to override, if you have determined integrity by other means."
|
|
|
|
[ "$PKGMK_IGNORE_SIG" = "yes" ] || { check_signature "pre-build" | parse_signify_output;
|
2022-05-31 16:02:44 -04:00
|
|
|
case $? in
|
|
|
|
0) info "Sources successfully authenticated." ;;
|
|
|
|
1) error "Signature file missing or corrupted." ; echo "$cs_fail_msg" ;;
|
|
|
|
2) error "Failed to authenticate remote sources using signify." ; echo "$cs_fail_msg" ;;
|
2022-06-01 05:58:13 -04:00
|
|
|
esac; }
|
2022-05-31 16:02:44 -04:00
|
|
|
[ "$PKGMK_CHECK_SIG" = "no" ] || exit 0 # no need to continue if the user only requested -cs
|
|
|
|
|
|
|
|
# What used to be called unpack_source() is now hard-coded into the main routine.
|
|
|
|
# If you need to shield specific source files from unpacking, use the "renames"
|
2022-06-01 17:37:01 -04:00
|
|
|
# feature of Pkgfile(5) to avoid matching any of the following patterns.
|
2022-05-31 16:02:44 -04:00
|
|
|
errUZ=0
|
|
|
|
for (( u=0; u<${#_local_[@]}; u++ )) ; do
|
|
|
|
here="${_local_[$u]}"
|
|
|
|
case "$here" in
|
|
|
|
*.tar|*.tar.gz|*.tar.Z|*.tgz|*.tar.bz2|*.tbz2|*.tar.xz|*.txz|*.tar.lzma|*.tar.lz|*.zip|*.rpm)
|
2022-06-01 06:27:29 -04:00
|
|
|
bsdtar -p -o -C src -xf "$here" || errUZ+=1 ;;
|
2022-05-31 16:02:44 -04:00
|
|
|
*)
|
|
|
|
cp -r "$here" src/ ;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
|
2022-06-01 10:55:07 -04:00
|
|
|
[ $errUZ = 0 ] && info "Sources successfully unpacked." || \
|
|
|
|
{ error "Failed to unpack all sources."; exit "$E_UNPACK"; }
|
|
|
|
[ "$PKGMK_EXTRACT_ONLY" = "no" ] || exit 0
|
2022-05-31 16:02:44 -04:00
|
|
|
|
|
|
|
# The actual build step!
|
|
|
|
if ! (SRC=$(pwd)/src; PKG=$(pwd)/pkg; cd src; set -x; build); then
|
|
|
|
error "Unsuccessful build!"; exit $E_BUILD
|
|
|
|
else
|
|
|
|
info "Build succeeded. Moving on to compression."
|
|
|
|
fi
|
|
|
|
|
2022-06-01 10:55:07 -04:00
|
|
|
[ -f "$PKGMK_ROOT/.nostrip" ] && ns_filter="| grep -v -f .nostrip"
|
2022-05-31 16:02:44 -04:00
|
|
|
find pkg -type f $ns_filter | while read -r f; do
|
|
|
|
case $(file -b "$f") in
|
|
|
|
*ELF*executable*not\ stripped*) strip --strip-all "$f" ;;
|
|
|
|
*ELF*shared\ object*not\ stripped*) strip --strip-unneeded "$f" ;;
|
|
|
|
current\ ar\ archive) strip --strip-debug "$f" ;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
|
2022-06-01 15:10:25 -04:00
|
|
|
find pkg -type f -path '*/man/man*/*' | grep -v '.gz$' | xargs -r -I{} gzip -9 '{}'
|
2022-05-31 16:02:44 -04:00
|
|
|
find pkg -xtype l -path '*/man/man*/*' -print0 \
|
|
|
|
| xargs -x -r -n1 sh -c "ln -sf \"\$(readlink -n '{}')\" '{}'"
|
|
|
|
|
|
|
|
[ $UID = 0 ] || fake_uid="--uid 0 --gid 0"
|
|
|
|
if (cd pkg; bsdtar --format=gnutar $fake_uid -cf "$pkg_dir$package" *); then
|
|
|
|
info "Package creation successful."
|
|
|
|
else
|
|
|
|
error "Unable to create the compressed package $package."
|
|
|
|
exit $E_DIRPERM
|
|
|
|
fi
|
|
|
|
|
2022-06-01 05:58:13 -04:00
|
|
|
# Ensure that $work/ contains the package or a symlink to it, then check the footprint
|
|
|
|
[ "$pkg_dir" = "$(pwd)/" ] || ln -sf "$pkg_dir$package" .
|
|
|
|
[ "$PKGMK_IGNORE_FOOTPRINT" = "yes" ] || check_manifest footprint || exit $E_MANIFEST
|
2022-05-31 16:02:44 -04:00
|
|
|
|
2022-06-01 05:58:13 -04:00
|
|
|
# Clean up, part 1: remove soft links and the {src,pkg} trees
|
|
|
|
find . -maxdepth 1 -mindepth 1 -type l -delete
|
2022-05-31 16:02:44 -04:00
|
|
|
[ "$PKGMK_KEEP_WORK" = "yes" ] || rm -rf src pkg
|
|
|
|
|
|
|
|
# Install if requested
|
|
|
|
# First find out how the effective user will invoke pkgadd
|
2022-06-01 20:05:15 -04:00
|
|
|
[ $UID = 0 ] || PKGMK_SU="sudo";
|
|
|
|
[ -z "$PKGMK_SU" ] || [ -x "$(command -v $PKGMK_SU)" ] || PKGMK_SU="/usr/bin/doas";
|
|
|
|
[ -x "$(command -v $PKGMK_SU)" ] || PKGMK_SU="su -c";
|
|
|
|
|
|
|
|
[ -z "$PKGMK_INSTALL_COMMAND" ] || { $PKGMK_SU $PKGMK_INSTALL_COMMAND "$pkg_dir$package" \
|
|
|
|
&& info "$(basename $PKGMK_INSTALL_COMMAND) $package succeeded."; } || \
|
|
|
|
{ error "Unable to install $package using pkgadd."; exit "$E_INSTALL"; }
|
2022-05-31 16:02:44 -04:00
|
|
|
|
|
|
|
# Clean up, part 2
|
|
|
|
[ "$PKGMK_KEEP_WORK" = "yes" ] || [ "$pkg_dir" = "$(pwd)/" ] || rm -f "$package"
|
|
|
|
|
|
|
|
# Done!
|
|
|
|
}
|
|
|
|
|
|
|
|
####################### error codes ##############################
|
|
|
|
E_PKGFILE=2 # invalid Pkgfile
|
2022-06-01 17:37:01 -04:00
|
|
|
E_DIRPERM=3 # (source/build) directory missing or missing read/write permission
|
2022-05-31 16:02:44 -04:00
|
|
|
E_DOWNLOAD=4 # error during download
|
|
|
|
E_UNPACK=5 # error during unpacking of source file(s)
|
2022-06-01 17:37:01 -04:00
|
|
|
E_MANIFEST=6 # footprint or md5sum failure
|
|
|
|
E_BUILD=7 # error while running 'build()'
|
|
|
|
E_INSTALL=8 # error while installing the package via 'pkgadd'
|
|
|
|
E_SIGNATURE=9 # error verifying the signature
|
2022-05-31 16:02:44 -04:00
|
|
|
|
|
|
|
######################## settings ################################
|
|
|
|
readonly PKGMK_VERSION="#VERSION#"
|
|
|
|
readonly PKGMK_COMMAND="$0"
|
|
|
|
readonly PKGMK_ROOT="$PWD"
|
|
|
|
readonly PKGMK_SIGNIFY="/usr/bin/signify"
|
|
|
|
readonly PRTWASH_COMMAND="/usr/bin/prtwash"
|
|
|
|
readonly PKGMK_GIT_COMMAND="/usr/bin/git"
|
|
|
|
PKGMK_DOWNLOAD_PROG="/usr/bin/wget"
|
|
|
|
|
|
|
|
PKGMK_CONF="/etc/pkgmk.conf"
|
|
|
|
PKGMK_SOURCE_DIR="$PWD"
|
|
|
|
PKGMK_PACKAGE_DIR="$PWD"
|
|
|
|
PKGMK_WORK_DIR="$PWD/work"
|
|
|
|
PKGMK_COMPRESSION_MODE="gz"
|
|
|
|
|
|
|
|
PKGMK_INSTALL_COMMAND=""
|
2022-06-01 08:31:21 -04:00
|
|
|
PKGMK_CLEAN="no"
|
2022-06-01 10:55:07 -04:00
|
|
|
PKGMK_RECURSIVE="no"
|
2022-05-31 16:02:44 -04:00
|
|
|
PKGMK_DOWNLOAD_ONLY="no"
|
|
|
|
PKGMK_EXTRACT_ONLY="no"
|
|
|
|
PKGMK_MTIME_ONLY="no"
|
|
|
|
PKGMK_UPDATE_FOOTPRINT="no"
|
|
|
|
PKGMK_IGNORE_FOOTPRINT="no"
|
|
|
|
PKGMK_IGNORE_NEW="no"
|
|
|
|
PKGMK_FORCE="no"
|
|
|
|
PKGMK_KEEP_WORK="no"
|
|
|
|
PKGMK_UPDATE_MD5="no"
|
|
|
|
PKGMK_IGNORE_MD5="no"
|
|
|
|
PKGMK_UPDATE_SIG="no"
|
|
|
|
PKGMK_IGNORE_SIG="no"
|
|
|
|
PKGMK_REFRESH_SIG="no"
|
|
|
|
PKGMK_CHECK_SIG="no"
|
|
|
|
PKGMK_PRIVATEKEY=""
|
|
|
|
|
|
|
|
######################## subroutines ################################
|
|
|
|
parse_options() {
|
|
|
|
while [ "$1" ]; do
|
|
|
|
case $1 in
|
2022-06-01 10:55:07 -04:00
|
|
|
-r|--recursive) PKGMK_RECURSIVE="yes" ;;
|
2022-06-01 05:58:13 -04:00
|
|
|
-c|--clean) [ -x "$PRTWASH_COMMAND" ] && PKGMK_CLEAN="yes" || \
|
|
|
|
{ error "option '-c' not supported ($PRTWASH_COMMAND not installed)";
|
|
|
|
exit 1; } ;;
|
2022-05-31 16:02:44 -04:00
|
|
|
-uf|--update-footprint) PKGMK_UPDATE_FOOTPRINT="yes" ;;
|
|
|
|
-um|--update-md5sum) PKGMK_UPDATE_MD5="yes" ;;
|
|
|
|
-us|--update-signature) PKGMK_UPDATE_SIG="yes" ;;
|
|
|
|
-rs|--refresh-signature) PKGMK_REFRESH_SIG="yes" ;;
|
|
|
|
-cs|--check-signature) PKGMK_CHECK_SIG="yes" ;;
|
|
|
|
-d|-cm|--download|--check-md5sum) ;;
|
|
|
|
-do|--download-only) PKGMK_DOWNLOAD_ONLY="yes" ;;
|
|
|
|
-eo|--extract-only) PKGMK_EXTRACT_ONLY="yes" ;;
|
|
|
|
-utd|--up-to-date) PKGMK_MTIME_ONLY="yes" ;;
|
|
|
|
-if|--ignore-footprint) PKGMK_IGNORE_FOOTPRINT="yes" ;;
|
|
|
|
-in|--ignore-new) PKGMK_IGNORE_NEW="yes" ;;
|
|
|
|
-im|--ignore-md5sum) PKGMK_IGNORE_MD5="yes" ;;
|
|
|
|
-is|--ignore-signature) PKGMK_IGNORE_SIG="yes" ;;
|
2022-06-01 10:55:07 -04:00
|
|
|
-ns|--no-strip) touch "$PKGMK_ROOT/.nostrip" ;;
|
2022-05-31 16:02:44 -04:00
|
|
|
-f|--force) PKGMK_FORCE="yes" ;;
|
|
|
|
-kw|--keep-work) PKGMK_KEEP_WORK="yes" ;;
|
|
|
|
-i|--install) PKGMK_INSTALL_COMMAND="/usr/bin/pkgadd" ;;
|
|
|
|
-u|--upgrade) PKGMK_INSTALL_COMMAND="/usr/bin/pkgadd -u" ;;
|
|
|
|
-pk|--public-key)
|
|
|
|
if [ ! "$2" ]; then
|
|
|
|
echo "$(basename "$PKGMK_COMMAND"): option $1 requires an argument"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
PKGMK_PUBLICKEY="$2"
|
|
|
|
shift ;;
|
|
|
|
-sk|--secret-key)
|
|
|
|
if [ ! "$2" ]; then
|
|
|
|
echo "$(basename "$PKGMK_COMMAND"): option $1 requires an argument"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
PKGMK_PRIVATEKEY="$2"
|
|
|
|
shift ;;
|
|
|
|
-cf|--config-file)
|
|
|
|
if [ ! "$2" ]; then
|
|
|
|
echo "$(basename "$PKGMK_COMMAND"): option $1 requires an argument"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
PKGMK_CONF="$2"
|
|
|
|
shift ;;
|
|
|
|
-v|--version)
|
|
|
|
echo "$(basename "$PKGMK_COMMAND") (pkgutils) $PKGMK_VERSION"
|
|
|
|
exit 0 ;;
|
|
|
|
-h|--help)
|
|
|
|
print_help
|
|
|
|
exit 0 ;;
|
|
|
|
*)
|
|
|
|
echo "$(basename "$PKGMK_COMMAND"): invalid option $1"
|
|
|
|
exit 1 ;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
print_help() {
|
|
|
|
echo "usage: $(basename "$PKGMK_COMMAND") [options]"
|
|
|
|
echo "options: "
|
|
|
|
echo " -r, --recursive search for Pkgfiles under $PWD, and run $(basename "$PKGMK_COMMAND")"
|
|
|
|
echo " with the other given options inside each directory found"
|
|
|
|
echo " -c, --clean remove package and downloaded files"
|
|
|
|
echo " -i, --install build and install package"
|
|
|
|
echo " -u, --upgrade build and install package (as upgrade)"
|
|
|
|
echo " -do, --download-only stop after downloading all the necessary source file(s)"
|
|
|
|
echo " -eo, --extract-only stop after downloading and extracting source file(s)"
|
2022-06-01 05:58:13 -04:00
|
|
|
echo " -utd, --up-to-date report whether the built package is up to date, then exit"
|
|
|
|
echo " -um, --update-md5sum update md5sum of the downloaded sources, do not build"
|
|
|
|
echo " -us, --update-signature update signature of Pkgfile and sources, do not build"
|
|
|
|
echo " -cs, --check-signature verify the signatures, do not build"
|
2022-05-31 16:02:44 -04:00
|
|
|
echo " -if, --ignore-footprint build package without checking footprint"
|
|
|
|
echo " -in, --ignore-new build package, ignoring new files in a footprint mismatch"
|
|
|
|
echo " -im, --ignore-md5sum build package without checking md5sum"
|
2022-06-01 05:58:13 -04:00
|
|
|
echo " -is, --ignore-signature build package without checking signature"
|
|
|
|
echo " -uf, --update-footprint update footprint using result from last build"
|
2022-05-31 16:02:44 -04:00
|
|
|
echo " -rs, --refresh-signature create new signature and keep existing sha256 checksums"
|
|
|
|
echo " -sk, --secret-key <file> use <file> to sign the port"
|
|
|
|
echo " -pk, --public-key <file> check the port signature using public-key <file>"
|
|
|
|
echo " -ns, --no-strip do not strip executable binaries or libraries"
|
|
|
|
echo " -f, --force build package even if it appears to be up to date"
|
|
|
|
echo " -kw, --keep-work keep temporary working directory"
|
|
|
|
echo " -cf, --config-file <file> use alternative configuration file"
|
|
|
|
echo " -v, --version print version and exit"
|
|
|
|
echo " -h, --help print help and exit"
|
|
|
|
}
|
|
|
|
|
|
|
|
validate_pkgfile() { # called from within PKGMK_ROOT
|
2022-06-01 05:58:13 -04:00
|
|
|
local errcode nn nv nr nb checksum absent
|
2022-05-31 16:02:44 -04:00
|
|
|
check_signature "pre-Pkgfile" | parse_signify_output
|
|
|
|
errcode=$?
|
|
|
|
[ "$errcode" = 0 ] || info "Use '-is' if you have confirmed its origin some other way."
|
2022-06-01 08:31:21 -04:00
|
|
|
[ "$errcode" = 0 ] || [ "$PKGMK_IGNORE_SIG" = "yes" ] || return $E_SIGNATURE
|
2022-05-31 16:02:44 -04:00
|
|
|
|
|
|
|
# the environment should not be affected by sourcing the Pkgfile both here
|
|
|
|
# and in the later build, but to be safe we use a nested subshell
|
|
|
|
( . Pkgfile; [ -n "$name" ] || nn=1; [ -n "$version" ] || nv=1; \
|
|
|
|
[ -n "$release" ] || nr=1; [ "$(type -t build)" = "function" ] || nb=1; \
|
2022-06-01 08:31:21 -04:00
|
|
|
echo $(( nn+2*nv+4*nr+8*nb )) ) | check_reqvars
|
|
|
|
}
|
|
|
|
|
|
|
|
check_reqvars () {
|
|
|
|
local checksum
|
2022-06-01 17:37:01 -04:00
|
|
|
read -r checksum
|
2022-06-01 08:31:21 -04:00
|
|
|
[ $((checksum & 1)) = 1 ] && absent=" 'name'"
|
|
|
|
[ $((checksum & 2)) = 2 ] && absent+=" 'version'"
|
|
|
|
[ $((checksum & 4)) = 4 ] && absent+=" 'release'"
|
|
|
|
[ $((checksum & 8)) = 8 ] && absent+=" 'build()'"
|
|
|
|
[ "$checksum" = 0 ] || { error "Pkgfile does not specify these required variables:"; \
|
|
|
|
info "$absent"; exit "$E_PKGFILE"; }
|
2022-05-31 16:02:44 -04:00
|
|
|
}
|
|
|
|
|
2022-06-01 05:58:13 -04:00
|
|
|
check_pkg_mtime() { # can be called even if some sources are missing
|
2022-06-01 15:10:25 -04:00
|
|
|
local li=0; local pkg_ood=1; local msg="$package is not up to date."
|
2022-05-31 16:02:44 -04:00
|
|
|
|
2022-06-01 15:10:25 -04:00
|
|
|
if [ -f "$pkg_dir$package" ]; then
|
|
|
|
pkg_ood=0
|
|
|
|
while [ $li -lt ${#_local_[@]} ] && [ "$pkg_ood" = 0 ]; do
|
2022-06-01 11:33:35 -04:00
|
|
|
[ ! -e "${_local_[$li]}" ] || \
|
2022-06-01 15:10:25 -04:00
|
|
|
[ $(realpath "${_local_[$li]}") -nt "$pkg_dir$package" ] || pkg_ood=1
|
2022-05-31 16:02:44 -04:00
|
|
|
li=$(( li+1 ))
|
|
|
|
done
|
2022-06-01 15:10:25 -04:00
|
|
|
[ ! -e Pkgfile ] || [ Pkgfile -nt "$pkg_dir$package" ] || pkg_ood=1
|
2022-05-31 16:02:44 -04:00
|
|
|
fi
|
|
|
|
|
2022-06-01 15:10:25 -04:00
|
|
|
[ "$pkg_ood" = 1 ] || msg="$package is up to date."
|
2022-06-01 10:55:07 -04:00
|
|
|
[ "$PKGMK_MTIME_ONLY" = "no" ] || info "$msg"
|
2022-05-31 16:02:44 -04:00
|
|
|
}
|
|
|
|
|
2022-06-01 05:58:13 -04:00
|
|
|
cat_manifest() {
|
2022-05-31 16:02:44 -04:00
|
|
|
case "$1" in
|
|
|
|
footprint)
|
|
|
|
pkginfo --footprint "$package" \
|
|
|
|
| sed "s|\tlib/modules/$(uname -r)/|\tlib/modules/<kernel-version>/|g" \
|
|
|
|
| sort -k 3
|
|
|
|
;;
|
|
|
|
md5sum)
|
|
|
|
[ ! -e "$PKGMK_ROOT/.signature" ] || [ "$PKGMK_UPDATE_MD5" = "yes" ] || return
|
|
|
|
md5sum "${_local_[@]}" 2>&1 \
|
|
|
|
| grep -v "is a directory" | sed 's, .*/, ,' | sort -k 2
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
|
|
|
check_manifest() {
|
|
|
|
local FILTER TRUTH CN CM
|
|
|
|
local FILE="$1.tmp"; local retval=0
|
2022-06-01 05:58:13 -04:00
|
|
|
[ -f "$package" ] || [ "$1" = "md5sum" ] || { error "$package not found. Cannot check $1.";
|
2022-05-31 16:02:44 -04:00
|
|
|
return "$E_MANIFEST"; }
|
|
|
|
[ "$1" = "md5sum" ] && FILTER="| sort -k 3" || FILTER=""
|
|
|
|
TRUTH="$PKGMK_ROOT/.$1"
|
|
|
|
|
2022-06-01 05:58:13 -04:00
|
|
|
cat_manifest $1 $FILTER > "$FILE"
|
2022-05-31 16:02:44 -04:00
|
|
|
if [ -f "$TRUTH" ]; then
|
|
|
|
cat "$TRUTH" $FILTER > "${FILE%tmp}orig"
|
|
|
|
diff -w -t -U 0 <(sort "${FILE%tmp}orig") <(sort "${FILE}") | \
|
|
|
|
sed '/^@@/d; /^+++/d; /^---/d; s/^+/NEW /g; s/^-/MISSING /g' \
|
|
|
|
> "${FILE%tmp}diff"
|
|
|
|
if [ -s "${FILE%tmp}diff" ]; then
|
|
|
|
error "$1 mismatch found:"
|
|
|
|
cat "${FILE%tmp}diff" >&2
|
|
|
|
CN=$(grep -c ^NEW "${FILE%tmp}diff")
|
|
|
|
CM=$(grep -c ^MISSING "${FILE%tmp}diff")
|
|
|
|
if [ "$1" = "footprint" ]; then
|
|
|
|
[ "$PKGMK_IGNORE_NEW" = "yes" ] || retval+=$CN
|
|
|
|
[ "$PKGMK_IGNORE_MISSING" = "yes" ] || retval+=$CM
|
|
|
|
retval=$(( E_MANIFEST*( retval>0 ) ))
|
|
|
|
else
|
|
|
|
retval=$E_MANIFEST
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
warning ".$1 not found, creating new."; mv "$FILE" "$TRUTH"
|
|
|
|
fi
|
|
|
|
return $retval
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_signify_output() { # chomps the output of check_signature()
|
|
|
|
local signout signerr
|
|
|
|
[ "$PKGMK_IGNORE_SIG" = "yes" ] && return 0
|
|
|
|
while read -r signout; do
|
|
|
|
case "$signout" in
|
2022-06-01 05:58:13 -04:00
|
|
|
*"Pkgfile verification failed")
|
|
|
|
signerr=-1; error "Signature missing! Unable to authenticate the Pkgfile."
|
|
|
|
;;
|
2022-05-31 16:02:44 -04:00
|
|
|
*"verification failed")
|
2022-06-01 05:58:13 -04:00
|
|
|
signerr=1; error "Signature file corrupted or unreadable."
|
2022-05-31 16:02:44 -04:00
|
|
|
;;
|
|
|
|
*"FAIL")
|
2022-06-01 05:58:13 -04:00
|
|
|
signerr=2; error "Signature mismatch found:"
|
2022-05-31 16:02:44 -04:00
|
|
|
echo "$signout" | awk -F: '/FAIL/ {printf "MISMATCH %s\n", $1}'
|
|
|
|
;;
|
2022-06-01 19:45:19 -04:00
|
|
|
*"OK") signerr=0 ;;
|
2022-05-31 16:02:44 -04:00
|
|
|
esac
|
|
|
|
done
|
|
|
|
return $signerr
|
|
|
|
}
|
|
|
|
|
2022-06-01 05:58:13 -04:00
|
|
|
check_signature() { # called from $PKGMK_ROOT in the case "when"="pre-Pkgfile",
|
2022-06-01 19:45:19 -04:00
|
|
|
# otherwise called from within $work. Pass control to
|
|
|
|
# check_manifest() if the signature is missing and "ignore-md5"
|
|
|
|
# has not been requested.
|
2022-06-01 17:37:01 -04:00
|
|
|
local reqfiles; local s=0; local when="$1"
|
2022-05-31 16:02:44 -04:00
|
|
|
|
|
|
|
if [ -f "$PKGMK_ROOT/.signature" ]; then
|
|
|
|
[ "$when" = "pre-Pkgfile" ] && reqfiles=(Pkgfile) || reqfiles=(.footprint)
|
2022-06-01 19:45:19 -04:00
|
|
|
while [ "$when" = "pre-build" ] && [ "$s" -lt ${#_local_[@]} ]; do
|
|
|
|
[[ "${source[$s]}" =~ ^(http|https|ssh|git).*/\.git ]] || \
|
|
|
|
reqfiles+=("${_local_[$s]}")
|
2022-05-31 16:02:44 -04:00
|
|
|
s=$(( s+1 ))
|
|
|
|
done
|
2022-06-01 19:45:19 -04:00
|
|
|
for FILE in "${reqfiles[@]}"; do
|
2022-05-31 16:02:44 -04:00
|
|
|
[ -e "$FILE" ] || ln -sf "$PKGMK_ROOT/$FILE" .
|
|
|
|
done
|
|
|
|
if [ -f "$PKGMK_PUBLICKEY" ]; then
|
2022-06-01 19:45:19 -04:00
|
|
|
$PKGMK_SIGNIFY -C -p "$PKGMK_PUBLICKEY" -x "$PKGMK_ROOT/.signature" \
|
2022-05-31 16:02:44 -04:00
|
|
|
"${reqfiles[@]}" 2>&1
|
|
|
|
else
|
2022-06-01 19:45:19 -04:00
|
|
|
$PKGMK_SIGNIFY -C -x "$PKGMK_ROOT/.signature" \
|
2022-05-31 16:02:44 -04:00
|
|
|
"${reqfiles[@]}" 2>&1
|
|
|
|
fi
|
|
|
|
else
|
2022-06-01 05:58:13 -04:00
|
|
|
[ "$when" != "pre-Pkgfile" ] || echo "Pkgfile verification failed"
|
2022-05-31 16:02:44 -04:00
|
|
|
[ "$when" = "pre-Pkgfile" ] || [ "$PKGMK_IGNORE_MD5" = "yes" ] || \
|
|
|
|
{ info "Signature not found, falling back to old md5sum checking.";
|
2022-06-01 05:58:13 -04:00
|
|
|
check_manifest md5sum ; }
|
2022-05-31 16:02:44 -04:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2022-06-01 05:58:13 -04:00
|
|
|
cat_signature() {
|
2022-06-01 20:16:15 -04:00
|
|
|
local ordered si key pub
|
2022-06-01 17:37:01 -04:00
|
|
|
[ -e "$PKGMK_ROOT/.footprint" ] || warning "Footprint not found, signature will be incomplete."
|
2022-05-31 16:02:44 -04:00
|
|
|
for key in ~/.ssh/*.sec /etc/ports/*.sec; do
|
2022-06-01 17:37:01 -04:00
|
|
|
[ -e "$key" ] || continue # workaround for brain-dead shell globbing
|
2022-05-31 16:02:44 -04:00
|
|
|
pub=/etc/ports/$(basename "${key/%.sec/.pub}")
|
|
|
|
if [ -e "$pub" ]; then
|
|
|
|
pub=$(readlink -f "$pub")
|
2022-06-01 17:37:01 -04:00
|
|
|
for f in "$PKGMK_ROOT/Pkgfile" "$PKGMK_ROOT/.footprint"; do
|
|
|
|
[ -e $f ] && ordered+=( "$f" )
|
|
|
|
done
|
2022-06-01 20:16:15 -04:00
|
|
|
for ((si=0; si < ${#source[@]}; si++)); do ordered+=("${_local_[$si]}"); done
|
|
|
|
sha256sum --tag "${ordered[@]}" \
|
2022-05-31 16:02:44 -04:00
|
|
|
| sed 's|^SHA256 (.*/\(.*\))\(.* = .*\)|SHA256 (\1)\2|' \
|
2022-06-01 17:37:01 -04:00
|
|
|
| "$PKGMK_SIGNIFY" -S -e -x - -q -s "$key" -m - \
|
2022-05-31 16:02:44 -04:00
|
|
|
| sed "s|${key/%.sec/.pub}|$pub|"
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
refresh_signature() {
|
|
|
|
if [ -e ".signature" ] && [ ! -w ".signature" ]; then
|
2022-06-01 05:58:13 -04:00
|
|
|
echo "error: .signature not writable."; return $E_DIRPERM
|
2022-05-31 16:02:44 -04:00
|
|
|
fi
|
|
|
|
|
|
|
|
local REPO
|
|
|
|
[ -n "$PKGMK_PRIVATEKEY" ] || REPO=$(dirname "$PWD" | sed 's|^.*/||; s|\.git$||;')
|
|
|
|
[ -n "$REPO" ] && PKGMK_PRIVATEKEY="/etc/ports/${REPO}.sec"
|
|
|
|
|
|
|
|
if ! tail -n +3 ".signature" | $PKGMK_SIGNIFY -S -e -x - -q \
|
|
|
|
-s "$PKGMK_PRIVATEKEY" -m - > .signature.tmp ; then
|
|
|
|
rm .signature.tmp
|
|
|
|
error "Refreshing signature failed"
|
|
|
|
return $E_SIGNATURE
|
|
|
|
else
|
|
|
|
mv .signature.tmp .signature
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
recursive() {
|
2022-06-01 10:55:07 -04:00
|
|
|
local ARGS DIR FILE
|
2022-06-01 17:37:01 -04:00
|
|
|
[ "$PKGMK_CLEAN" = "no" ] || { find "$PKGMK_ROOT" -name Pkgfile -printf "%h\n" \
|
2022-06-01 05:58:13 -04:00
|
|
|
| xargs "$PRTWASH_COMMAND" -s -p -b -q; exit $? ; }
|
2022-05-31 16:02:44 -04:00
|
|
|
|
2022-06-01 08:31:21 -04:00
|
|
|
ARGS=$(echo "$@" | sed "s/--recursive//g; s/\s*-r\s*/ /g")
|
2022-06-01 10:55:07 -04:00
|
|
|
for FILE in $(find "$PKGMK_ROOT" -name Pkgfile | sort); do
|
|
|
|
DIR=$(dirname "$FILE")
|
|
|
|
[ -d $DIR ] && { info "Entering directory '$DIR'.";
|
|
|
|
(cd "$DIR" && "$PKGMK_COMMAND" $ARGS);
|
|
|
|
info "Leaving directory '$DIR'."; }
|
2022-05-31 16:02:44 -04:00
|
|
|
done
|
2022-06-01 08:31:21 -04:00
|
|
|
exit
|
2022-05-31 16:02:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
info() {
|
|
|
|
echo "=======> $1"
|
|
|
|
}
|
|
|
|
|
|
|
|
warning() {
|
|
|
|
info "WARNING: $1" >&2
|
|
|
|
}
|
|
|
|
|
|
|
|
error() {
|
|
|
|
info "ERROR: $1" >&2
|
|
|
|
}
|
|
|
|
|
|
|
|
######################## end of subroutines ###########################
|
|
|
|
## Now ensure that they cannot be overwritten when sourcing Pkgfile ##
|
2022-06-01 08:31:21 -04:00
|
|
|
readonly -f main info warning error print_help parse_options recursive \
|
|
|
|
validate_pkgfile check_reqvars check_pkg_mtime cat_manifest check_manifest \
|
|
|
|
cat_signature check_signature parse_signify_output refresh_signature
|
2022-05-31 16:02:44 -04:00
|
|
|
|
|
|
|
main "$@"
|