#!/bin/sh ## Licensed under ## BSD License (2-clause) ## https://opensource.org/licenses/BSD-2-Clause ## Copyright (c) 2015, John D. "Trix" Farrar ## pkgng module for CFEngine 3.7+ if [ -n "$CFENGINE_TEST_PKGNG_MOCK" ]; then alias pkg='./mock_pkgng' fi CMD="$1" PKG_OPTIONS='' REPO='' INPUTLIST='' mangle_arch() { awk 'BEGIN { arch["x86:32"] = "i386"; arch["x86:64"] = "amd64"; arch["aarch64:64"] = "aarch64"; arch["armv6:32:el:eabi:softfp"] = "armv6"; arch["armv7:32:el:eabi:softfp"] = "armv7"; arch["mips:32:eb:o32"] = "mips"; arch["mips:64:eb:n64"] = "mips64"; arch["powerpc:64:eb"] = "powerpc64"; } { for (a in arch) { re = ":" a "$"; sub(re, ":" arch[a]); } sub(/[Ff]ree[Bb][Ss][Dd]:[0-9]*:/, ""); } $0' } fatal() { echo "ErrorMessage=$*" exit 1 } parse_line() { echo "$1" | awk -F= '{ i=index($0,"="); print "KEYWORD=\"" $1 "\"" "; VALUE=\"" substr($0, i+1) "\""; }' 2>/dev/null } read_options() { while read -r INPUT ; do if [ -n "${INPUT}" ] ; then eval `parse_line "${INPUT}"` case "${KEYWORD}" in File|Name) if [ "${KEYWORD}" = 'File' ] ; then PKG="${VALUE}" else NAM="${VALUE}" fi ;; Version|Architecture) # Do not store the value separately, as process_inputs() # will get it from $INPUTLIST ;; options) eval `parse_line "${VALUE}"` case "${KEYWORD}" in repo|repository) REPO="-r ${VALUE}";; option) PKG_OPTIONS="${PKG_OPTIONS} -o ${VALUE}";; esac continue ;; PackageType*) TYP="${VALUE}" ;; *) fatal "Invalid input: '${KEYWORD}'." ;; esac if [ -n "${KEYWORD}" ] && [ -n "${VALUE}" ] ; then if [ -n "${INPUTLIST}" ] ; then INPUTLIST="${INPUTLIST} ${KEYWORD}=${VALUE}" else INPUTLIST="${KEYWORD}=${VALUE}" fi fi fi done } process_inputs() { CMD="$1" ; shift OPTIONS="$*" for OPT in ${OPTIONS} ; do eval `parse_line ${OPT}` case "${KEYWORD}" in File*) if [ "${CMD}" = 'file-install' ] ; then PKG="${PKG} ${VALUE}" else fatal "Bad Input: '${OPT}' (should be Name=...)." fi ;; Name*) if [ "${CMD}" != 'file-install' ] ; then PKG="${PKG} ${VALUE}" else fatal "Bad Input: '${OPT}' (should be File=...)" fi ;; Version*) PKG="${PKG}-${VALUE}" ;; Architecture*) if [ -n "${VALUE}" ] && [ "${VALUE}" != "${ARCH}" ] ; then fatal "Bad Input: Architecture ${VALUE} does not match ${ARCH}." fi ;; PackageType*) TYP="${VALUE}" ;; *) fatal "Invalid input: '${INPUT}'." ;; esac done } _pkg() { pkg ${PKG_OPTIONS} "$@" } _pkg_query() { _pkg query "$@" "Name=%n\nVersion=%v\nArchitecture=${ARCH}" } get_package_data() { if [ -n "${NAM}" ] && [ -z "${PKG}" ] ; then PKG="${NAM}" fi if [ -n "${PKG}" ] ; then case "${PKG}" in /*) # File Path. It's a file TYP='file' if [ ! -e "${PKG}" ] ; then fatal "No such file: '${PKG}'." fi ;; http://*|ftp://|file://) # URL, it's a file. TYP='file' ;; *) TYP='repo' ;; esac echo "PackageType=${TYP}" if [ "${TYP}" = 'repo' ] ; then PKGNAM=`basename "${PKG}" | sed -r -e 's/^([A-Za-z0-9_-]+)-[0-9a-z.,_]+/\1/'` PKGVER=`basename "${PKG}" | sed -r -e 's/^[A-Za-z0-9_-]+-([0-9a-z.,_]+)/\1/' -e 's/\.(tgz|(tar\.)?gz|txz|zip)$//'` if [ -z "`echo ${PKGVER} | grep -E '^[0-9]'`" ] ; then if [ "${PKGNAM}" != "${PKGVER}" ] ; then PKGNAM="${PKGNAM}-${PKGVER}" fi PKGVER='' fi echo "Name=${PKGNAM}" # Returning version for PackageType=repo is not advised # https://docs.cfengine.com/latest/reference-standard-library-package_modules.html # if [ -n "${PKGVER}" ] ; then # echo "Version=${PKGVER}" # fi else _pkg_query --file "${PKG}" fi fi } if [ "${CMD}" = 'supports-api-version' ] ; then echo '1' exit 0 else read_options fi ARCH=$(_pkg config abi | mangle_arch) case "${CMD}" in get-package-data) get_package_data ;; list-installed) _pkg_query -a ;; list-updates-local|list-updates) if [ "${CMD}" = 'list-updates-local' ] ; then LOCALUPDATE='-U' else LOCALUPDATE='' fi _pkg version ${LOCALUPDATE} -vl'<' | \ awk -v arch="${ARCH}" \ '/ repositor(y|ies) / { next; } { pkgname = $1; pkgver = $7; sub(/-[0-9_.,]*$/, "", pkgname); sub(/\)/, "", pkgver); print "Name=" pkgname; print "Version=" pkgver; print "Architecture=" arch; }' ;; repo-install|file-install|remove) process_inputs "${CMD}" "${INPUTLIST}" case "${CMD}" in repo-install) _pkg install -qy ${REPO} ${PKG} 2>/dev/null >/dev/null ;; file-install) _pkg install -qy ${PKG} 2>/dev/null >/dev/null ;; remove) _pkg delete -Rqy ${PKG} 2>/dev/null >/dev/null ;; esac RC=$? if [ ${RC} -ne 0 ] ; then fatal "Package manager error" exit $RC fi ;; *) fatal "Command '${CMD}' is either not valid or not implemented." ;; esac