#!/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 ################################ local o_ignored work _local_ here url u f pkg_utd local errDL=0; local errUZ=0; parse_options "$@" [ "$PKGMK_RECURSIVE" = "no" ] || recursive "$@" # # 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:"; info "$o_ignored"; } exec $PRTWASH_COMMAND -p -s -q "$(pwd)" fi # # Read the Pkgfile to determine what to do next. But first ensure that # it came from a trusted source (FS#1851) # validate_pkgfile || exit $E_PKGFILE [ -f .32bit ] && PGKMK_ARCH=32 || PKGMK_ARCH=64 . "Pkgfile"; . "$PKGMK_CONF"; set -e # respect the settings for centralized source and package directories ... [ -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= # ... and for WORK_DIR in case the user wants to build in RAM [ -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 if [[ ${source[$s]} =~ ^(http|https|ssh|git)://.*/(.+)\.git ]]; then _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" # Determine whether git can be used to obtain sources PKGMK_GIT_COMMAND="/usr/bin/git" [ -x "$PKGMK_GIT_COMMAND" ] || PKGMK_GIT_COMMAND="/bin/true" # Skip the retrieval of sources if the user only asked for '-utd' [ "$PKGMK_MTIME_ONLY" = "yes" ] || { for (( u=0; u<${#_local_[@]}; u++ )); do here="${_local_[$u]}"; url="${source[$u]}"; # at least one of the following commands should put a file of the # appropriate name in the current directory [ -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" ) ; # but if not, exit with an informative error message [ -e "$here" ] || { error "failed to download $here. Check connection and try again."; errDL+=1; } done ; } [ $errDL != 0 ] || info "Successfully obtained all needed source files." # If the user only asked for '-utd', perform the check using the sources that do exist. check_pkg_mtime; pkg_utd=$? [ "$PKGMK_MTIME_ONLY" = "no" ] || [ "$PKGMK_CHECK_SIG" = "yes" ] || exit $pkg_utd # Some further tests before proceeding with the build [ "$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) )) # Take into account all the actions that can be done with a previously built package, # or with a full set of sources [ "$pkg_utd" = 0 ] || [ "$PKGMK_FORCE" = "yes" ] || [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ] \ || [ "$PKGMK_UPDATE_SIG" = "yes" ] || [ "$PKGMK_CHECK_SIG" = "yes" ] \ || [ "$PKGMK_UPDATE_MD5" = "yes" ] || [ "$PKGMK_EXTRACT_ONLY" = "yes" ] \ || { info "$package is up to date, use '-f' to force a rebuild."; exit 0; } # Silence the progress report if the user never intended to proceed with unpacking [ "$pkg_utd" = 1 ] || [ "$PKGMK_CHECK_SIG" = "yes" ] || echo "Checking signatures before unpacking..." # 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. if [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ]; then [ -f "$package" ] || \ { error "unable to update footprint. File '$package' not found."; exit "$E_MANIFEST"; } [ "$pkg_utd" = 1 ] || [ "$PKGMK_FORCE" = "yes" ] || \ { error "outdated package. Use '-f' to force the footprint update."; exit "$E_FOOTPRINT"; } cat_manifest footprint > "$PKGMK_ROOT/.footprint" || \ { error "Failed to write the footprint."; exit "$E_DIRPERM"; } fi [ "$PKGMK_UPDATE_SIG" = "no" ] || \ { cat_signature > "$PKGMK_ROOT/.signature" && info "Signature successfully created."; } || \ { 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" ] || \ { cat_manifest md5sum > "$PKGMK_ROOT"/.md5sum && info "md5sum updated."; } || \ { info "Could not create requested md5sums."; exit "$E_DIRPERM"; } # 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" ]; then exit 0 fi # All the sources should be here by now, let's verify that we can trust them. 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; 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" ;; esac; } [ "$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" # feature of Pkgfile(5) to avoid matching any of the following patterns. if [ "$pkg_utd" = 0 ] || [ "$PKGMK_FORCE" = "yes" ]; then 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) bsdtar -p -o -C src -xf "$here" || errUZ+=1 ;; *) cp -r "$here" src/ ;; esac done [ $errUZ != 0 ] || info "Sources successfully unpacked." || \ { error "Failed to unpack all sources."; exit "$E_UNPACK"; } [ "$PKGMK_EXTRACT_ONLY" = "no" ] || exit 0 # The actual build step! (SRC=$(pwd)/src; PKG=$(pwd)/pkg; cd src; set -x; build) && info "Build succeeded. Moving on to compression." || { error "Unsuccessful build!"; exit "$E_BUILD"; } [ -f "$PKGMK_ROOT/.nostrip" ] && ns_filter="| grep -v -f .nostrip" 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 find pkg -type f -path '*/man/man*/*' | grep -v '.gz$' | xargs -r -I{} gzip -9 '{}' 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 # 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 # Clean up, part 1: remove soft links and the {src,pkg} trees find . -maxdepth 1 -mindepth 1 -type l -delete [ "$PKGMK_KEEP_WORK" = "yes" ] || rm -rf src pkg fi # Continue from here if the extract and build were skipped # Install if requested # First find out how the effective user will invoke pkgadd [ $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"; } # Clean up, part 2 [ "$PKGMK_KEEP_WORK" = "yes" ] || [ "$pkg_dir" = "$(pwd)/" ] || rm -f "$package" # Done! } ####################### error codes ############################## E_PKGFILE=2 # invalid Pkgfile E_DIRPERM=3 # (source/build) directory missing or missing read/write permission E_DOWNLOAD=4 # error during download E_UNPACK=5 # error during unpacking of source file(s) 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 ######################## settings ################################ readonly PKGMK_VERSION="#VERSION#" readonly PKGMK_COMMAND="$0" readonly PKGMK_ROOT="$PWD" readonly PRTWASH_COMMAND="/usr/bin/prtwash" 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="" PKGMK_CLEAN="no" PKGMK_RECURSIVE="no" 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 -r|--recursive) PKGMK_RECURSIVE="yes" ;; -c|--clean) [ -x "$PRTWASH_COMMAND" ] && PKGMK_CLEAN="yes" || \ { error "option '-c' not supported ($PRTWASH_COMMAND not installed)"; exit 1; } ;; -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" ;; -ns|--no-strip) touch "$PKGMK_ROOT/.nostrip" ;; -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) [ "$2" ] || { echo "$(basename "$PKGMK_COMMAND"): option $1 requires an argument"; exit 1; } PKGMK_PUBLICKEY="$2" shift ;; -sk|--secret-key) [ "$2" ] || { echo "$(basename "$PKGMK_COMMAND"): option $1 requires an argument"; exit 1; } PKGMK_PRIVATEKEY="$2" shift ;; -cf|--config-file) [ "$2" ] || { echo "$(basename "$PKGMK_COMMAND"): option $1 requires an argument"; exit 1; } 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)" 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" 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" echo " -is, --ignore-signature build package without checking signature" echo " -uf, --update-footprint update footprint using result from last build" echo " -rs, --refresh-signature create new signature and keep existing sha256 checksums" echo " -sk, --secret-key use to sign the port" echo " -pk, --public-key check the port signature using public-key " 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 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 local errcode kv check_signature "pre-Pkgfile" | parse_signify_output errcode=$? [ "$errcode" = 0 ] || info "Use '-is' if you have independent confirmation of the port's integrity." [ "$errcode" = 0 ] || [ "$PKGMK_IGNORE_SIG" = "yes" ] || return $E_SIGNATURE # 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; kv=0; [ -n "$name" ] || kv+=1; [ -n "$version" ] || kv+=2; \ [ -n "$release" ] || kv+=4; [ "$(type -t build)" = "function" ] || kv+=8; \ echo $kv ) | check_reqvars } check_reqvars () { local checksum read -r checksum [ $((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"; } } check_pkg_mtime() { # can be called even if some sources are missing local li=0; local utd=0; local msg="$package is not up to date." if [ -f "$pkg_dir$package" ]; then utd=1 while [ $li -lt ${#_local_[@]} ] && [ "$utd" = 1 ]; do [ ! -e "${_local_[$li]}" ] || \ [ $(realpath "${_local_[$li]}") -nt "$pkg_dir$package" ] || utd=0 li=$(( li+1 )) done [ ! -e Pkgfile ] || [ Pkgfile -nt "$pkg_dir$package" ] || utd=0 fi [ $utd = 0 ] || msg="$package is up to date." info "$msg"; return $utd } cat_manifest() { case "$1" in footprint) pkginfo --footprint "$package" \ | sed "s|\tlib/modules/$(uname -r)/|\tlib/modules//|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 [ -f "$package" ] || [ "$1" = "md5sum" ] || { error "$package not found. Cannot check $1."; return "$E_MANIFEST"; } [ "$1" = "md5sum" ] && FILTER="| sort -k 3" || FILTER="" TRUTH="$PKGMK_ROOT/.$1" cat_manifest $1 $FILTER > "$FILE" 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 *"Pkgfile verification failed") signerr=-1; error "Signature missing! Unable to authenticate the Pkgfile." ;; *"verification failed") signerr=1; error "Signature file corrupted or unreadable." ;; *"FAIL") signerr=2; error "Signature mismatch found:" echo "$signout" | awk -F: '/FAIL/ {printf "MISMATCH %s\n", $1}' ;; *"OK") signerr=0 ;; esac done return $signerr } check_signature() { # called from $PKGMK_ROOT in the case "when"="pre-Pkgfile", # otherwise called from within $work. Pass control to # check_manifest() if the signature is missing and "ignore-md5" # has not been requested. # Remember to clean up the soft links that get left behind! local reqfiles=(Pkgfile); local s=0; local when="$1" if [ -f "$PKGMK_ROOT/.signature" ]; then [ "$when" = "pre-Pkgfile" ] || reqfiles=(.footprint) while [ "$when" = "pre-build" ] && [ "$s" -lt ${#_local_[@]} ]; do [[ "${source[$s]}" =~ ^(http|https|ssh|git).*/\.git ]] || \ reqfiles+=("${_local_[$s]}") s=$(( s+1 )) done for FILE in "${reqfiles[@]}"; do [ -e "$FILE" ] || ln -sf "$PKGMK_ROOT/$FILE" . done if [ -f "$PKGMK_PUBLICKEY" ]; then /usr/bin/signify -C -p "$PKGMK_PUBLICKEY" -x "$PKGMK_ROOT/.signature" \ "${reqfiles[@]}" 2>&1 else /usr/bin/signify -C -x "$PKGMK_ROOT/.signature" \ "${reqfiles[@]}" 2>&1 fi else [ "$when" != "pre-Pkgfile" ] || echo "Pkgfile verification failed" [ "$when" = "pre-Pkgfile" ] || [ "$PKGMK_IGNORE_MD5" = "yes" ] || \ { info "Signature not found, falling back to old md5sum checking."; check_manifest md5sum ; } fi } cat_signature() { local ordered si key pub [ -e "$PKGMK_ROOT/.footprint" ] || warning "Footprint not found, signature will be incomplete." for key in ~/.ssh/*.sec /etc/ports/*.sec; do [ -e "$key" ] || continue # workaround for brain-dead shell globbing pub=/etc/ports/$(basename "${key/%.sec/.pub}") if [ -e "$pub" ]; then pub=$(readlink -f "$pub") for f in "$PKGMK_ROOT/Pkgfile" "$PKGMK_ROOT/.footprint"; do [ -e $f ] && ordered+=( "$f" ) done for ((si=0; si < ${#source[@]}; si++)); do ordered+=("${_local_[$si]}"); done sha256sum --tag "${ordered[@]}" \ | sed 's|^SHA256 (.*/\(.*\))\(.* = .*\)|SHA256 (\1)\2|' \ | /usr/bin/signify -S -e -x - -q -s "$key" -m - \ | sed "s|${key/%.sec/.pub}|$pub|" break fi done } refresh_signature() { if [ -e ".signature" ] && [ ! -w ".signature" ]; then echo "error: .signature not writable."; return $E_DIRPERM 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" | /usr/bin/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() { local ARGS DIR FILE [ "$PKGMK_CLEAN" = "no" ] || { find "$PKGMK_ROOT" -name Pkgfile -printf "%h\n" \ | xargs "$PRTWASH_COMMAND" -s -p -b -q; exit $? ; } ARGS=$(echo "$@" | sed "s/--recursive//g; s/\s*-r\s*/ /g") 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'."; } done exit } 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 ## 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 main "$@"