pkgutils/pkgmk.in
Brett Goulder 765b5014db Bug #241: Don't check SSL certificates.
pkgmk's mechanism to check file integrity is .md5sum, so relying on
proper SSL certificates for https connections isn't critical. This fixes
transfers from https servers whose SSL certificates are self signed only.

Original patch by Jose V Beneyto <sepen@users.sourceforge.net>.
2008-04-11 18:48:57 +02:00

679 lines
14 KiB
Bash
Executable File

#!/bin/bash
#
# pkgutils
#
# Copyright (c) 2000-2005 Per Liden
# Copyright (c) 2006-2007 by CRUX team (http://crux.nu)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
# USA.
#
info() {
echo "=======> $1"
}
warning() {
info "WARNING: $1" >&2
}
error() {
info "ERROR: $1" >&2
}
get_filename() {
local FILE="`echo $1 | sed 's|^.*://.*/||g'`"
if [ "$FILE" != "$1" ]; then
FILE="$PKGMK_SOURCE_DIR/$FILE"
fi
echo $FILE
}
get_basename() {
local FILE="`echo $1 | sed 's|^.*://.*/||g'`"
echo $FILE
}
check_pkgfile() {
if [ ! "$name" ]; then
error "Variable 'name' not specified in $PKGMK_PKGFILE."
exit 1
elif [ ! "$version" ]; then
error "Variable 'version' not specified in $PKGMK_PKGFILE."
exit 1
elif [ ! "$release" ]; then
error "Variable 'release' not specified in $PKGMK_PKGFILE."
exit 1
elif [ "`type -t build`" != "function" ]; then
error "Function 'build' not specified in $PKGMK_PKGFILE."
exit 1
fi
}
check_directory() {
if [ ! -d $1 ]; then
error "Directory '$1' does not exist."
exit 1
elif [ ! -w $1 ]; then
error "Directory '$1' not writable."
exit 1
elif [ ! -x $1 ] || [ ! -r $1 ]; then
error "Directory '$1' not readable."
exit 1
fi
}
download_file() {
info "Downloading '$1'."
if [ ! "`type -p wget`" ]; then
error "Command 'wget' not found."
exit 1
fi
LOCAL_FILENAME=`get_filename $1`
LOCAL_FILENAME_PARTIAL="$LOCAL_FILENAME.partial"
DOWNLOAD_OPTS="--passive-ftp --no-directories --tries=3 --waitretry=3 \
--directory-prefix=$PKGMK_SOURCE_DIR \
--output-document=$LOCAL_FILENAME_PARTIAL --no-check-certificate"
if [ -f "$LOCAL_FILENAME_PARTIAL" ]; then
info "Partial download found, trying to resume"
RESUME_CMD="-c"
fi
error=1
BASENAME=`get_basename $1`
for REPO in ${PKGMK_SOURCE_MIRRORS[@]}; do
REPO="`echo $REPO | sed 's|/$||'`"
wget $RESUME_CMD $DOWNLOAD_OPTS $REPO/$BASENAME
error=$?
if [ $error == 0 ]; then
break
fi
done
if [ $error != 0 ]; then
while true; do
wget $RESUME_CMD $DOWNLOAD_OPTS $1
error=$?
if [ $error != 0 ] && [ "$RESUME_CMD" ]; then
info "Partial download failed, restarting"
rm -f "$LOCAL_FILENAME_PARTIAL"
RESUME_CMD=""
else
break
fi
done
fi
if [ $error != 0 ]; then
error "Downloading '$1' failed."
exit 1
fi
mv -f "$LOCAL_FILENAME_PARTIAL" "$LOCAL_FILENAME"
}
download_source() {
local FILE LOCAL_FILENAME
for FILE in ${source[@]}; do
LOCAL_FILENAME=`get_filename $FILE`
if [ ! -e $LOCAL_FILENAME ]; then
if [ "$LOCAL_FILENAME" = "$FILE" ]; then
error "Source file '$LOCAL_FILENAME' not found (can not be downloaded, URL not specified)."
exit 1
else
if [ "$PKGMK_DOWNLOAD" = "yes" ]; then
download_file $FILE
else
error "Source file '$LOCAL_FILENAME' not found (use option -d to download)."
exit 1
fi
fi
fi
done
}
unpack_source() {
local FILE LOCAL_FILENAME COMMAND
for FILE in ${source[@]}; do
LOCAL_FILENAME=`get_filename $FILE`
case $LOCAL_FILENAME in
*.tar.gz|*.tar.Z|*.tgz)
COMMAND="tar -C $SRC --use-compress-program=gzip -xf $LOCAL_FILENAME" ;;
*.tar.bz2)
COMMAND="tar -C $SRC --use-compress-program=bzip2 -xf $LOCAL_FILENAME" ;;
*.zip)
COMMAND="unzip -qq -o -d $SRC $LOCAL_FILENAME" ;;
*)
COMMAND="cp $LOCAL_FILENAME $SRC" ;;
esac
echo "$COMMAND"
$COMMAND
if [ $? != 0 ]; then
if [ "$PKGMK_KEEP_WORK" = "no" ]; then
rm -rf $PKGMK_WORK_DIR
fi
error "Building '$TARGET' failed."
exit 1
fi
done
}
make_md5sum() {
local FILE LOCAL_FILENAMES
if [ "$source" ]; then
for FILE in ${source[@]}; do
LOCAL_FILENAMES="$LOCAL_FILENAMES `get_filename $FILE`"
done
md5sum $LOCAL_FILENAMES | sed -e 's| .*/| |' | sort -k 2
fi
}
make_footprint() {
pkginfo --footprint $TARGET | \
sed "s|\tlib/modules/`uname -r`/|\tlib/modules/<kernel-version>/|g" | \
sort -k 3
}
check_md5sum() {
local FILE="$PKGMK_WORK_DIR/.tmp"
cd $PKGMK_ROOT
if [ -f $PKGMK_MD5SUM ]; then
make_md5sum > $FILE.md5sum
sort -k 2 $PKGMK_MD5SUM > $FILE.md5sum.orig
diff -w -t -U 0 $FILE.md5sum.orig $FILE.md5sum | \
sed '/^@@/d' | \
sed '/^+++/d' | \
sed '/^---/d' | \
sed 's/^+/NEW /g' | \
sed 's/^-/MISSING /g' > $FILE.md5sum.diff
if [ -s $FILE.md5sum.diff ]; then
error "Md5sum mismatch found:"
cat $FILE.md5sum.diff >&2
if [ "$PKGMK_KEEP_WORK" = "no" ]; then
rm -rf $PKGMK_WORK_DIR
fi
if [ "$PKGMK_CHECK_MD5SUM" = "yes" ]; then
error "Md5sum not ok."
exit 1
fi
error "Building '$TARGET' failed."
exit 1
fi
else
if [ "$PKGMK_CHECK_MD5SUM" = "yes" ]; then
if [ "$PKGMK_KEEP_WORK" = "no" ]; then
rm -rf $PKGMK_WORK_DIR
fi
info "Md5sum not found."
exit 1
fi
warning "Md5sum not found, creating new."
make_md5sum > $PKGMK_MD5SUM
fi
if [ "$PKGMK_CHECK_MD5SUM" = "yes" ]; then
if [ "$PKGMK_KEEP_WORK" = "no" ]; then
rm -rf $PKGMK_WORK_DIR
fi
info "Md5sum ok."
exit 0
fi
}
strip_files() {
local FILE FILTER
cd $PKG
if [ -f $PKGMK_ROOT/$PKGMK_NOSTRIP ]; then
FILTER="grep -v -f $PKGMK_ROOT/$PKGMK_NOSTRIP"
else
FILTER="cat"
fi
find . -type f -printf "%P\n" | $FILTER | while read FILE; do
case $(file -b "$FILE") in
*ELF*executable*not\ stripped)
strip --strip-all "$FILE"
;;
*ELF*shared\ object*not\ stripped)
strip --strip-unneeded "$FILE"
;;
current\ ar\ archive)
strip --strip-debug "$FILE"
esac
done
}
compress_manpages() {
local FILE DIR TARGET
cd $PKG
find . -type f -path "*/man/man*/*" | while read FILE; do
if [ "$FILE" = "${FILE%%.gz}" ]; then
gzip -9 "$FILE"
fi
done
find . -type l -path "*/man/man*/*" | while read FILE; do
TARGET=`readlink -n "$FILE"`
TARGET="${TARGET##*/}"
TARGET="${TARGET%%.gz}.gz"
rm -f "$FILE"
FILE="${FILE%%.gz}.gz"
DIR=`dirname "$FILE"`
if [ -e "$DIR/$TARGET" ]; then
ln -sf "$TARGET" "$FILE"
fi
done
}
check_footprint() {
local FILE="$PKGMK_WORK_DIR/.tmp"
cd $PKGMK_ROOT
if [ -f $TARGET ]; then
make_footprint > $FILE.footprint
if [ -f $PKGMK_FOOTPRINT ]; then
sort -k 3 $PKGMK_FOOTPRINT > $FILE.footprint.orig
diff -w -t -U 0 $FILE.footprint.orig $FILE.footprint | \
sed '/^@@/d' | \
sed '/^+++/d' | \
sed '/^---/d' | \
sed 's/^+/NEW /g' | \
sed 's/^-/MISSING /g' > $FILE.footprint.diff
if [ -s $FILE.footprint.diff ]; then
error "Footprint mismatch found:"
cat $FILE.footprint.diff >&2
BUILD_SUCCESSFUL="no"
fi
else
warning "Footprint not found, creating new."
mv $FILE.footprint $PKGMK_FOOTPRINT
fi
else
error "Package '$TARGET' was not found."
BUILD_SUCCESSFUL="no"
fi
}
build_package() {
local BUILD_SUCCESSFUL="no"
export PKG="$PKGMK_WORK_DIR/pkg"
export SRC="$PKGMK_WORK_DIR/src"
umask 022
cd $PKGMK_ROOT
rm -rf $PKGMK_WORK_DIR
mkdir -p $SRC $PKG
if [ "$PKGMK_IGNORE_MD5SUM" = "no" ]; then
check_md5sum
fi
if [ "$UID" != "0" ]; then
warning "Packages should be built as root."
fi
info "Building '$TARGET'."
unpack_source
cd $SRC
(set -e -x ; build)
if [ $? = 0 ]; then
if [ "$PKGMK_NO_STRIP" = "no" ]; then
strip_files
fi
compress_manpages
cd $PKG
info "Build result:"
tar czvvf $TARGET *
if [ $? = 0 ]; then
BUILD_SUCCESSFUL="yes"
if [ "$PKGMK_IGNORE_FOOTPRINT" = "yes" ]; then
warning "Footprint ignored."
else
check_footprint
fi
fi
fi
if [ "$PKGMK_KEEP_WORK" = "no" ]; then
rm -rf $PKGMK_WORK_DIR
fi
if [ "$BUILD_SUCCESSFUL" = "yes" ]; then
info "Building '$TARGET' succeeded."
else
if [ -f $TARGET ]; then
touch -r $PKGMK_ROOT/$PKGMK_PKGFILE $TARGET &> /dev/null
fi
error "Building '$TARGET' failed."
exit 1
fi
}
install_package() {
local COMMAND
info "Installing '$TARGET'."
if [ "$PKGMK_INSTALL" = "install" ]; then
COMMAND="pkgadd $TARGET"
else
COMMAND="pkgadd -u $TARGET"
fi
cd $PKGMK_ROOT
echo "$COMMAND"
$COMMAND
if [ $? = 0 ]; then
info "Installing '$TARGET' succeeded."
else
error "Installing '$TARGET' failed."
exit 1
fi
}
recursive() {
local ARGS FILE DIR
ARGS=`echo "$@" | sed -e "s/--recursive//g" -e "s/-r//g"`
for FILE in `find $PKGMK_ROOT -name $PKGMK_PKGFILE | sort`; do
DIR="`dirname $FILE`/"
if [ -d $DIR ]; then
info "Entering directory '$DIR'."
(cd $DIR && $PKGMK_COMMAND $ARGS)
info "Leaving directory '$DIR'."
fi
done
}
clean() {
local FILE LOCAL_FILENAME
if [ -f $TARGET ]; then
info "Removing $TARGET"
rm -f $TARGET
fi
for FILE in ${source[@]}; do
LOCAL_FILENAME=`get_filename $FILE`
if [ -e $LOCAL_FILENAME ] && [ "$LOCAL_FILENAME" != "$FILE" ]; then
info "Removing $LOCAL_FILENAME"
rm -f $LOCAL_FILENAME
fi
done
}
update_footprint() {
if [ ! -f $TARGET ]; then
error "Unable to update footprint. File '$TARGET' not found."
exit 1
fi
make_footprint > $PKGMK_FOOTPRINT
touch $TARGET
info "Footprint updated."
}
build_needed() {
local FILE RESULT
RESULT="yes"
if [ -f $TARGET ]; then
RESULT="no"
for FILE in $PKGMK_PKGFILE ${source[@]}; do
FILE=`get_filename $FILE`
if [ ! -e $FILE ] || [ ! $TARGET -nt $FILE ]; then
RESULT="yes"
break
fi
done
fi
echo $RESULT
}
interrupted() {
echo ""
error "Interrupted."
if [ "$PKGMK_KEEP_WORK" = "no" ]; then
rm -rf $PKGMK_WORK_DIR
fi
exit 1
}
print_help() {
echo "usage: `basename $PKGMK_COMMAND` [options]"
echo "options:"
echo " -i, --install build and install package"
echo " -u, --upgrade build and install package (as upgrade)"
echo " -r, --recursive search for and build packages recursively"
echo " -d, --download download missing source file(s)"
echo " -do, --download-only do not build, only download missing source file(s)"
echo " -utd, --up-to-date do not build, only check if package is up to date"
echo " -uf, --update-footprint update footprint using result from last build"
echo " -if, --ignore-footprint build package without checking footprint"
echo " -um, --update-md5sum update md5sum"
echo " -im, --ignore-md5sum build package without checking md5sum"
echo " -cm, --check-md5sum do not build, only check md5sum"
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 " -c, --clean remove package and downloaded files"
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"
}
parse_options() {
while [ "$1" ]; do
case $1 in
-i|--install)
PKGMK_INSTALL="install" ;;
-u|--upgrade)
PKGMK_INSTALL="upgrade" ;;
-r|--recursive)
PKGMK_RECURSIVE="yes" ;;
-d|--download)
PKGMK_DOWNLOAD="yes" ;;
-do|--download-only)
PKGMK_DOWNLOAD="yes"
PKGMK_DOWNLOAD_ONLY="yes" ;;
-utd|--up-to-date)
PKGMK_UP_TO_DATE="yes" ;;
-uf|--update-footprint)
PKGMK_UPDATE_FOOTPRINT="yes" ;;
-if|--ignore-footprint)
PKGMK_IGNORE_FOOTPRINT="yes" ;;
-um|--update-md5sum)
PKGMK_UPDATE_MD5SUM="yes" ;;
-im|--ignore-md5sum)
PKGMK_IGNORE_MD5SUM="yes" ;;
-cm|--check-md5sum)
PKGMK_CHECK_MD5SUM="yes" ;;
-ns|--no-strip)
PKGMK_NO_STRIP="yes" ;;
-f|--force)
PKGMK_FORCE="yes" ;;
-c|--clean)
PKGMK_CLEAN="yes" ;;
-kw|--keep-work)
PKGMK_KEEP_WORK="yes" ;;
-cf|--config-file)
if [ ! "$2" ]; then
echo "`basename $PKGMK_COMMAND`: option $1 requires an argument"
exit 1
fi
PKGMK_CONFFILE="$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
}
main() {
local FILE TARGET
parse_options "$@"
if [ "$PKGMK_RECURSIVE" = "yes" ]; then
recursive "$@"
exit 0
fi
for FILE in $PKGMK_PKGFILE $PKGMK_CONFFILE; do
if [ ! -f $FILE ]; then
error "File '$FILE' not found."
exit 1
fi
. $FILE
done
check_directory "$PKGMK_SOURCE_DIR"
check_directory "$PKGMK_PACKAGE_DIR"
check_directory "`dirname $PKGMK_WORK_DIR`"
check_pkgfile
TARGET="$PKGMK_PACKAGE_DIR/$name#$version-$release.pkg.tar.gz"
if [ "$PKGMK_CLEAN" = "yes" ]; then
clean
exit 0
fi
if [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ]; then
update_footprint
exit 0
fi
if [ "$PKGMK_UPDATE_MD5SUM" = "yes" ]; then
download_source
make_md5sum > $PKGMK_MD5SUM
info "Md5sum updated."
exit 0
fi
if [ "$PKGMK_DOWNLOAD_ONLY" = "yes" ]; then
download_source
exit 0
fi
if [ "$PKGMK_UP_TO_DATE" = "yes" ]; then
if [ "`build_needed`" = "yes" ]; then
info "Package '$TARGET' is not up to date."
else
info "Package '$TARGET' is up to date."
fi
exit 0
fi
if [ "`build_needed`" = "no" ] && [ "$PKGMK_FORCE" = "no" ] && [ "$PKGMK_CHECK_MD5SUM" = "no" ]; then
info "Package '$TARGET' is up to date."
else
download_source
build_package
fi
if [ "$PKGMK_INSTALL" != "no" ]; then
install_package
fi
exit 0
}
trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM
export LC_ALL=POSIX
readonly PKGMK_VERSION="#VERSION#"
readonly PKGMK_COMMAND="$0"
readonly PKGMK_ROOT="$PWD"
PKGMK_CONFFILE="/etc/pkgmk.conf"
PKGMK_PKGFILE="Pkgfile"
PKGMK_FOOTPRINT=".footprint"
PKGMK_MD5SUM=".md5sum"
PKGMK_NOSTRIP=".nostrip"
PKGMK_SOURCE_MIRRORS=()
PKGMK_SOURCE_DIR="$PWD"
PKGMK_PACKAGE_DIR="$PWD"
PKGMK_WORK_DIR="$PWD/work"
PKGMK_INSTALL="no"
PKGMK_RECURSIVE="no"
PKGMK_DOWNLOAD="no"
PKGMK_DOWNLOAD_ONLY="no"
PKGMK_UP_TO_DATE="no"
PKGMK_UPDATE_FOOTPRINT="no"
PKGMK_IGNORE_FOOTPRINT="no"
PKGMK_FORCE="no"
PKGMK_KEEP_WORK="no"
PKGMK_UPDATE_MD5SUM="no"
PKGMK_IGNORE_MD5SUM="no"
PKGMK_CHECK_MD5SUM="no"
PKGMK_NO_STRIP="no"
PKGMK_CLEAN="no"
main "$@"
# End of file