pkgmeek: refactored a few subroutines
This commit is contained in:
parent
f28c0cf330
commit
682fc883e5
190
scripts/pkgmeek
190
scripts/pkgmeek
@ -20,7 +20,7 @@ if [ "$PKGMK_CLEAN" = "yes" ]; then
|
||||
[ "$PKGMK_REFRESH_SIG" = "yes" ] && refresh_signature
|
||||
[ "$o_ignored" = "" ] || { warning "option -c nullifies these requested options:";
|
||||
echo "$o_ignored"; }
|
||||
exec $PRTWASH_COMMAND -p -s "$(pwd)"
|
||||
exec $PRTWASH_COMMAND -p -s -q "$(pwd)"
|
||||
fi
|
||||
#
|
||||
# Read the Pkgfile to determine what to do next. But first ensure that
|
||||
@ -64,11 +64,11 @@ done
|
||||
[ -w "$(dirname "$work")" ] || work="$(pwd)"/work
|
||||
rm -rf "$work"; mkdir -p "$work"/{src,pkg} && cd "$work"
|
||||
|
||||
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
|
||||
# Skip the retrieval of sources if the user only asked for '-utd'
|
||||
[ "$PKGMK_MTIME_ONLY" = "yes" ] || { errDL=0; 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 ]] || {
|
||||
@ -80,22 +80,25 @@ for (( u=0; u<${#_local_[@]}; u++ )); do
|
||||
# but if not, exit with an informative error message
|
||||
if [ ! -e "$here" ]; then
|
||||
error "failed to download $here. Check connection and try again."
|
||||
errDL=$E_DOWNLOAD
|
||||
errDL+=1
|
||||
fi
|
||||
done
|
||||
done; }
|
||||
|
||||
{ [ "$PKGMK_DOWNLOAD_ONLY" = "yes" ] || [ "$errDL" ]; } && exit $errDL
|
||||
|
||||
# Now that all the files are on disk, check mtimes to determine whether a build is needed.
|
||||
# If the user only asked for '-utd', perform the check using the sources that do exist.
|
||||
check_pkg_mtime && pkg_ood=0 || pkg_ood=1
|
||||
[ "$PKGMK_MTIME_ONLY" = "no" ] || exit $pkg_ood
|
||||
|
||||
# If the user did NOT ask for '-utd' or '-do', then all sources must be present.
|
||||
{ [ "$PKGMK_DOWNLOAD_ONLY" = "yes" ] || [ "$errDL" ] ; } && exit $(( E_DOWNLOAD*(errDL>0) ))
|
||||
|
||||
# Some further tests before proceeding with the build
|
||||
[ "$pkg_ood" = 1 ] || [ "$PKGMK_FORCE" = "yes" ] || [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ] || \
|
||||
[ "$PKGMK_UPDATE_SIG" = "yes" ] || exit 0
|
||||
[ "$PKGMK_UPDATE_SIG" = "yes" ] || [ "$PKGMK_UPDATE_MD5" = "yes" ] || exit 0
|
||||
[ "$PKGMK_CHECK_SIG" = "yes" ] || echo "Checking signatures before unpacking..."
|
||||
|
||||
# The option -uf is meant to be used after a previous invocation of pkgmk has
|
||||
# alerted the user to a footprint mismatch. The option -us is likewise meant
|
||||
# to update the signature, which only requires the sources and the footprint.
|
||||
# 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.";
|
||||
@ -103,25 +106,33 @@ if [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ]; then
|
||||
[ "$pkg_ood" = 0 ] || [ "$PKGMK_FORCE" = "yes" ] || \
|
||||
{ error "outdated package. Use '-f' to force the footprint update.";
|
||||
exit "$E_FOOTPRINT"; }
|
||||
make_manifest "footprint" > "$PKGMK_ROOT/.footprint" || \
|
||||
cat_manifest footprint > "$PKGMK_ROOT/.footprint" || \
|
||||
{ error "Failed to write the footprint."; exit "$E_DIRPERM"; }
|
||||
fi
|
||||
if [ "$PKGMK_UPDATE_SIG" = "yes" ]; then
|
||||
make_signature > "$PKGMK_ROOT/.signature" ||
|
||||
{ error "Failed to update signature."; exit "$E_DIRPERM"; }
|
||||
fi
|
||||
if [ "$PKGMK_UPDATE_SIG" = "yes" ] || [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ];
|
||||
[ "$PKGMK_UPDATE_SIG" = "no" ] || \
|
||||
{ cat_signature > "$PKGMK_ROOT/.signature" &&
|
||||
echo "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 "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 their integrity by other means."
|
||||
check_signature "pre-build" | parse_signify_output
|
||||
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
|
||||
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.
|
||||
@ -168,45 +179,23 @@ 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
|
||||
|
||||
# The $work directory now has a symlink to the package, so check its footprint
|
||||
if ! check_manifest "footprint" ; then
|
||||
[ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ] && make_manifest "footprint" > "$PKGMK_ROOT"/.footprint
|
||||
[ "$PKGMK_IGNORE_FOOTPRINT" = "no" ] && exit $E_MANIFEST
|
||||
fi
|
||||
|
||||
# Fulfill any *explicit* requests for (signed) manifests, then exit
|
||||
# (disposal of the work directory is retained from the first run of pkgmeek)
|
||||
[ -f "$PKGMK_ROOT/.signature" ] || [ "$PKGMK_UPDATE_SIG" = "no" ] || \
|
||||
warning "Signature not found, creating new."
|
||||
[ "$PKGMK_UPDATE_SIG" = "no" ] || \
|
||||
{ make_signature > "$PKGMK_ROOT/.signature" &&
|
||||
echo "Signature successfully created."; } || \
|
||||
{ make_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" ] || \
|
||||
make_manifest "md5sum" >"$PKGMK_ROOT"/.md5sum || \
|
||||
{ info "Could not create requested md5sums."; exit "$E_DIRPERM"; }
|
||||
if [ "$PKGMK_UPDATE_SIG" = "yes" ] || [ "$PKGMK_UPDATE_MD5" = "yes" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Clean up, part 1
|
||||
# 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
|
||||
|
||||
# Install if requested
|
||||
# First find out how the effective user will invoke pkgadd
|
||||
case $UID in
|
||||
0) SUDO="" ;;
|
||||
*) SUDO="sudo " ;;
|
||||
esac
|
||||
[ -z "$SUDO" ] || [ -x $(command -v "$SUDO") ] || SUDO="/usr/bin/doas "
|
||||
[ -x $(command -v "$SUDO") ] || SUDO="su -c"
|
||||
[ $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";
|
||||
|
||||
if [ "$PKGMK_INSTALL_COMMAND" ]; then
|
||||
if ! $SUDO $PKGMK_INSTALL_COMMAND "$package"; then
|
||||
if ! $PKGMK_SU $PKGMK_INSTALL_COMMAND "$package"; then
|
||||
error "Unable to install $package using pkgadd."
|
||||
exit $E_INSTALL
|
||||
fi
|
||||
@ -263,10 +252,13 @@ PKGMK_NOSTRIP=".nostrip"
|
||||
|
||||
######################## subroutines ################################
|
||||
parse_options() {
|
||||
ARGV=( "$@" ) # retain all arguments in case '-r' was not the first
|
||||
while [ "$1" ]; do
|
||||
case $1 in
|
||||
-r|--recursive) recursive "$@" ;;
|
||||
-c|--clean) PKGMK_CLEAN="yes" ;;
|
||||
-r|--recursive) recursive "$ARGV" ;;
|
||||
-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" ;;
|
||||
@ -330,15 +322,15 @@ print_help() {
|
||||
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 check whether the built package is up to date, then exit"
|
||||
echo " -uf, --update-footprint update footprint using result from last build"
|
||||
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 " -um, --update-md5sum update md5sum"
|
||||
echo " -im, --ignore-md5sum build package without checking md5sum"
|
||||
echo " -cs, --check-signature verify the signatures, do not proceed with the build"
|
||||
echo " -us, --update-signature update signatures only, do not proceed with the build"
|
||||
echo " -is, --ignore-signature build package without checking the signature"
|
||||
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 <file> use <file> to sign the port"
|
||||
echo " -pk, --public-key <file> check the port signature using public-key <file>"
|
||||
@ -351,7 +343,7 @@ print_help() {
|
||||
}
|
||||
|
||||
validate_pkgfile() { # called from within PKGMK_ROOT
|
||||
local errcode nn nv nr nb
|
||||
local errcode nn nv nr nb checksum absent
|
||||
check_signature "pre-Pkgfile" | parse_signify_output
|
||||
errcode=$?
|
||||
[ "$errcode" = 0 ] || info "Use '-is' if you have confirmed its origin some other way."
|
||||
@ -361,28 +353,17 @@ validate_pkgfile() { # called from within PKGMK_ROOT
|
||||
# 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; \
|
||||
echo $(( nn+2*nv+4*nr+8*nb )) ) | check_required_vars
|
||||
echo $(( nn+2*nv+4*nr+8*nb )) ) | { 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_required_vars() {
|
||||
local checksum absent v
|
||||
read -r checksum
|
||||
|
||||
[ $((checksum & 1)) = 1 ] && absent=("'name'")
|
||||
[ $((checksum & 2)) = 2 ] && absent=("${absent[@]}" "'version'")
|
||||
[ $((checksum & 4)) = 4 ] && absent=("${absent[@]}" "'release'")
|
||||
[ $((checksum & 8)) = 8 ] && absent=("${absent[@]}" "'build()'")
|
||||
|
||||
if [ "$checksum" -gt 0 ]; then
|
||||
error "Pkgfile does not specify these required variables:"
|
||||
for v in "${absent[@]}"; do
|
||||
echo -n "$v "
|
||||
done
|
||||
echo; exit $E_PKGFILE
|
||||
fi
|
||||
}
|
||||
|
||||
check_pkg_mtime() { # only called before a build attempt, not again after a successful build
|
||||
check_pkg_mtime() { # can be called even if some sources are missing
|
||||
local status=1; local li=0; local pkg_ood="yes"
|
||||
|
||||
if [ -f "$package" ]; then
|
||||
@ -402,7 +383,7 @@ check_pkg_mtime() { # only called before a build attempt, not again after a succ
|
||||
return $status
|
||||
}
|
||||
|
||||
make_manifest() {
|
||||
cat_manifest() {
|
||||
case "$1" in
|
||||
footprint)
|
||||
pkginfo --footprint "$package" \
|
||||
@ -420,12 +401,12 @@ make_manifest() {
|
||||
check_manifest() {
|
||||
local FILTER TRUTH CN CM
|
||||
local FILE="$1.tmp"; local retval=0
|
||||
[ ! -f "$package" ] && { error "$package not found. Cannot check $1.";
|
||||
[ -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"
|
||||
|
||||
make_manifest $1 $FILTER > "$FILE"
|
||||
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}") | \
|
||||
@ -455,11 +436,14 @@ parse_signify_output() { # chomps the output of check_signature()
|
||||
[ "$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; echo "Signature file corrupted or unreadable."
|
||||
signerr=1; error "Signature file corrupted or unreadable."
|
||||
;;
|
||||
*"FAIL")
|
||||
signerr=2; echo "Signature mismatch found:"
|
||||
signerr=2; error "Signature mismatch found:"
|
||||
echo "$signout" | awk -F: '/FAIL/ {printf "MISMATCH %s\n", $1}'
|
||||
;;
|
||||
esac
|
||||
@ -467,13 +451,13 @@ parse_signify_output() { # chomps the output of check_signature()
|
||||
return $signerr
|
||||
}
|
||||
|
||||
check_signature() {
|
||||
# called from within the src subdir unless "when"="pre-Pkgfile".
|
||||
# Pass control to check_manifest() if the signature is missing and
|
||||
# "ignore-md5" has not been requested.
|
||||
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.
|
||||
local reqfiles s
|
||||
local when="$1"
|
||||
[ "$PKGMK_IGNORE_SIG" = "yes" ] && echo; return
|
||||
|
||||
|
||||
if [ -f "$PKGMK_ROOT/.signature" ]; then
|
||||
[ "$when" = "pre-Pkgfile" ] && reqfiles=(Pkgfile) || reqfiles=(.footprint)
|
||||
@ -493,15 +477,14 @@ check_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" ; }
|
||||
check_manifest md5sum ; }
|
||||
fi
|
||||
# remove soft links
|
||||
[ "$when" = "post-build" ] && find . -maxdepth 1 -mindepth 1 -type l -delete
|
||||
}
|
||||
|
||||
make_signature() {
|
||||
cat_signature() {
|
||||
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}")
|
||||
@ -520,8 +503,7 @@ make_signature() {
|
||||
|
||||
refresh_signature() {
|
||||
if [ -e ".signature" ] && [ ! -w ".signature" ]; then
|
||||
echo "error: .signature not writable."
|
||||
return $E_SIGNATURE
|
||||
echo "error: .signature not writable."; return $E_DIRPERM
|
||||
fi
|
||||
|
||||
local REPO
|
||||
@ -540,8 +522,8 @@ refresh_signature() {
|
||||
|
||||
recursive() {
|
||||
local ARGS FILE DIR
|
||||
[ "$PKGMK_CLEAN" == "no" ] || { find "$PKGMK_ROOT" -name Pkgfile \
|
||||
-printf "%h\n" | xargs "$PRTWASH_COMMAND" -s -p -b ; exit $? ; }
|
||||
[ "$PKGMK_CLEAN" == "no" ] || { find "$PKGMK_ROOT" -name Pkgfile -printf "%h\n" \
|
||||
| xargs "$PRTWASH_COMMAND" -s -p -b -q; exit $? ; }
|
||||
|
||||
ARGS=$(echo "$@" | sed -e "s/--recursive//g; s/[ ]+-r[ ]+/ /g")
|
||||
for FILE in $(find "$PKGMK_ROOT" -name Pkgfile | sort); do
|
||||
@ -568,8 +550,8 @@ error() {
|
||||
|
||||
######################## end of subroutines ###########################
|
||||
## Now ensure that they cannot be overwritten when sourcing Pkgfile ##
|
||||
readonly -f main parse_options print_help validate_pkgfile check_required_vars \
|
||||
check_pkg_mtime make_manifest check_manifest check_signature make_signature \
|
||||
readonly -f main parse_options print_help validate_pkgfile check_pkg_mtime \
|
||||
cat_manifest check_manifest cat_signature check_signature \
|
||||
parse_signify_output refresh_signature recursive
|
||||
|
||||
main "$@"
|
||||
|
Loading…
Reference in New Issue
Block a user