summaryrefslogtreecommitdiffstats
path: root/scripts/makepkg.sh.in
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/makepkg.sh.in')
-rw-r--r--scripts/makepkg.sh.in161
1 files changed, 153 insertions, 8 deletions
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 6fb36d27..9e0a667d 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -28,7 +28,7 @@
# makepkg uses quite a few external programs during its execution. You
# need to have at least the following installed for makepkg to function:
# awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils),
-# gettext, grep, gzip, openssl, sed, tput (ncurses), xz
+# gettext, gpg, grep, gzip, openssl, sed, tput (ncurses), xz
# gettext initialization
export TEXTDOMAIN='pacman'
@@ -75,6 +75,7 @@ CHECKFUNC=0
PKGFUNC=0
SPLITPKG=0
PKGLIST=()
+SIGNPKG=''
# Forces the pkgver of the current PKGBUILD. Used by the fakeroot call
# when dealing with svn/cvs/etc PKGBUILDs.
@@ -391,7 +392,7 @@ run_pacman() {
local cmd
printf -v cmd "%q " "$PACMAN" $PACMAN_OPTS "$@"
if (( ! ASROOT )) && [[ ! $1 =~ ^-(T|Qq)$ ]]; then
- if [ "$(type -p sudo)" ]; then
+ if type -p sudo >/dev/null; then
cmd="sudo $cmd"
else
cmd="su root -c '$cmd'"
@@ -855,7 +856,7 @@ tidy_install() {
fi
if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then
- msg2 "$(gettext "Purging other files...")"
+ msg2 "$(gettext "Purging unwanted files...")"
local pt
for pt in "${PURGE_TARGETS[@]}"; do
if [[ ${pt} = ${pt//\/} ]]; then
@@ -931,6 +932,58 @@ tidy_install() {
fi
}
+find_libdepends() {
+ local libdepends
+ find "$pkgdir" -type f -perm -u+x | while read filename
+ do
+ # get architecture of the file; if soarch is empty it's not an ELF binary
+ soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
+ [ -n "$soarch" ] || continue
+ # process all libraries needed by the binary
+ for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
+ do
+ # extract the library name: libfoo.so
+ soname="${sofile%%\.so\.*}.so"
+ # extract the major version: 1
+ soversion="${sofile##*\.so\.}"
+ if in_array "${soname}" ${depends[@]}; then
+ if ! in_array "${soname}=${soversion}-${soarch}" ${libdepends[@]}; then
+ # libfoo.so=1-64
+ echo "${soname}=${soversion}-${soarch}"
+ libdepends=(${libdepends[@]} "${soname}=${soversion}-${soarch}")
+ fi
+ fi
+ done
+ done
+}
+
+find_libprovides() {
+ local libprovides
+ find "$pkgdir" -type f -name \*.so\* | while read filename
+ do
+ # check if we really have a shared object
+ if LC_ALL=C readelf -h "$filename" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
+ # 64
+ soarch=$(LC_ALL=C readelf -h "$filename" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
+ # get the string binaries link to: libfoo.so.1.2 -> libfoo.so.1
+ sofile=$(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
+ [ -z "$sofile" ] && sofile="${$filename##*/}"
+
+ # extract the library name: libfoo.so
+ soname="${sofile%%\.so\.*}.so"
+ # extract the major version: 1
+ soversion="${sofile##*\.so\.}"
+ if in_array "${soname}" ${provides[@]}; then
+ if ! in_array "${soname}=${soversion}-${soarch}" ${libprovides[@]}; then
+ # libfoo.so=1-64
+ echo "${soname}=${soversion}-${soarch}"
+ libprovides=(${libprovides[@]} "${soname}=${soversion}-${soarch}")
+ fi
+ fi
+ fi
+ done
+}
+
write_pkginfo() {
local builddate=$(date -u "+%s")
if [[ -n $PACKAGER ]]; then
@@ -960,13 +1013,44 @@ write_pkginfo() {
[[ $license ]] && printf "license = %s\n" "${license[@]}"
[[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
[[ $groups ]] && printf "group = %s\n" "${groups[@]}"
- [[ $depends ]] && printf "depend = %s\n" "${depends[@]}"
[[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]}"
[[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
- [[ $provides ]] && printf "provides = %s\n" "${provides[@]}"
[[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
local it
+
+ libprovides=$(find_libprovides)
+ libdepends=$(find_libdepends)
+ provides=("${provides[@]}" ${libprovides})
+ depends=("${depends[@]}" ${libdepends})
+
+ for it in "${depends[@]}"; do
+ if [[ $it = *.so ]]; then
+ # check if the entry has been found by find_libdepends
+ # if not, it's unneeded; tell the user so he can remove it
+ if [[ ! $libdepends =~ (^|\s)${it}=.* ]]; then
+ error "$(gettext "Can't find library listed in \$depends: %s")" "$it"
+ return 1
+ fi
+ else
+ echo "depend = $it"
+ fi
+ done
+
+ for it in "${provides[@]}"; do
+ # ignore versionless entires (those come from the PKGBUILD)
+ if [[ $it = *.so ]]; then
+ # check if the entry has been found by find_libprovides
+ # if not, it's unneeded; tell the user so he can remove it
+ if [[ ! $libprovides =~ (^|\s)${it}=.* ]]; then
+ error "$(gettext "Can't find library listed in \$provides: %s")" "$it"
+ return 1
+ fi
+ else
+ echo "provides = $it"
+ fi
+ done
+
for it in "${packaging_options[@]}"; do
local ret="$(check_option $it)"
if [[ $ret != "?" ]]; then
@@ -1065,6 +1149,9 @@ create_package() {
local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${PKGARCH}${PKGEXT}"
local ret=0
+ [[ -f $pkg_file ]] && rm -f "$pkg_file"
+ [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
+
# when fileglobbing, we want * in an empty directory to expand to
# the null string rather than itself
shopt -s nullglob
@@ -1086,9 +1173,12 @@ create_package() {
exit 1 # TODO: error code
fi
+ create_signature "$pkg_file"
+
if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
ln -sf "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
ret=$?
+ [[ -f $pkg_file.sig ]] && ln -sf "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
fi
if (( ret )); then
@@ -1096,6 +1186,33 @@ create_package() {
fi
}
+create_signature() {
+ if [[ $SIGNPKG != 'y' ]]; then
+ return
+ fi
+ local ret=0
+ local filename="$1"
+ msg "$(gettext "Signing package...")"
+ if ! type -p gpg >/dev/null; then
+ error "$(gettext "Cannot find the gpg binary! Is gnupg installed?")"
+ exit 1 # $E_MISSING_PROGRAM
+ fi
+
+ local SIGNWITHKEY=""
+ if [[ -n $GPGKEY ]]; then
+ SIGNWITHKEY="-u ${GPGKEY}"
+ fi
+ # The signature will be generated directly in ascii-friendly format
+ gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$?
+
+
+ if (( ! ret )); then
+ msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
+ else
+ warning "$(gettext "Failed to sign package file.")"
+ fi
+}
+
create_srcpackage() {
cd "$startdir"
@@ -1573,7 +1690,7 @@ usage() {
echo "$(gettext " -e, --noextract Do not extract source files (use existing src/ dir)")"
echo "$(gettext " -f, --force Overwrite existing package")"
echo "$(gettext " -g, --geninteg Generate integrity checks for source files")"
- echo "$(gettext " -h, --help This help")"
+ echo "$(gettext " -h, --help Show this help message and exit")"
echo "$(gettext " -i, --install Install package after successful build")"
echo "$(gettext " -L, --log Log package build process")"
echo "$(gettext " -m, --nocolor Disable colorized output messages")"
@@ -1587,8 +1704,11 @@ usage() {
printf "$(gettext " --check Run the check() function in the %s")\n" "$BUILDSCRIPT"
printf "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
printf "$(gettext " --holdver Prevent automatic version bumping for development %ss")\n" "$BUILDSCRIPT"
+ echo "$(gettext " --key <key> Specify a key to use for gpg signing instead of the default")"
printf "$(gettext " --nocheck Do not run the check() function in the %s")\n" "$BUILDSCRIPT"
+ echo "$(gettext " --nosign Do not create a signature for the package")"
echo "$(gettext " --pkg <list> Only build listed packages from a split package")"
+ echo "$(gettext " --sign Sign the resulting package with gpg")"
echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")"
echo "$(gettext " --source Generate a source-only tarball without downloaded sources")"
echo
@@ -1625,8 +1745,8 @@ ARGLIST=("$@")
OPT_SHORT="AcCdefFghiLmop:rRsV"
OPT_LONG="allsource,asroot,ignorearch,check,clean,cleancache,nodeps"
OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver"
-OPT_LONG+=",install,log,nocolor,nobuild,nocheck,pkg:,rmdeps"
-OPT_LONG+=",repackage,skipinteg,source,syncdeps,version,config:"
+OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps"
+OPT_LONG+=",repackage,skipinteg,sign,source,syncdeps,version,config:"
# Pacman Options
OPT_LONG+=",noconfirm,noprogressbar"
OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@" || echo 'PARSE_OPTIONS FAILED')"
@@ -1660,15 +1780,18 @@ while true; do
-g|--geninteg) GENINTEG=1 ;;
--holdver) HOLDVER=1 ;;
-i|--install) INSTALL=1 ;;
+ --key) shift; GPGKEY=$1 ;;
-L|--log) LOGGING=1 ;;
-m|--nocolor) USE_COLOR='n' ;;
--nocheck) RUN_CHECK='n' ;;
+ --nosign) SIGNPKG='n' ;;
-o|--nobuild) NOBUILD=1 ;;
-p) shift; BUILDFILE=$1 ;;
--pkg) shift; PKGLIST=($1) ;;
-r|--rmdeps) RMDEPS=1 ;;
-R|--repackage) REPKG=1 ;;
--skipinteg) SKIPINTEG=1 ;;
+ --sign) SIGNPKG='y' ;;
--source) SOURCEONLY=1 ;;
-s|--syncdeps) DEP_BIN=1 ;;
@@ -1685,6 +1808,9 @@ done
[[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
[[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
[[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
+[[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
+[[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
+[[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
# default config is makepkg.conf
MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
@@ -1748,6 +1874,9 @@ fi
SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined
+PKGEXT=${_PKGEXT:-$PKGEXT}
+SRCEXT=${_SRCEXT:-$SRCEXT}
+GPGKEY=${_GPGKEY:-$GPGKEY}
if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then
# The '\\0' is here to prevent gettext from thinking --holdver is an option
@@ -1899,6 +2028,22 @@ if [[ -n "${PKGLIST[@]}" ]]; then
pkgname=("${PKGLIST[@]}")
fi
+# check if gpg signature is to be created and if signing key is valid
+if [[ -z "$SIGNPKG" && $(check_buildenv sign) == 'y' ]]; then
+ SIGNPKG='y'
+fi
+if [[ $SIGNPKG == 'y' ]]; then
+ if ! gpg --list-key ${GPGKEY} &>/dev/null; then
+ if [[ ! -z $GPGKEY ]]; then
+ error "$(gettext "The key ${GPGKEY} does not exist in your keyring.")"
+ else
+ error "$(gettext "There is no key in your keyring.")"
+ fi
+ exit 1
+ fi
+fi
+
+
if (( ! SPLITPKG )); then
fullver=$(get_full_version $epoch $pkgver $pkgrel)
if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \