#!/bin/bash # # common.sh: common functions for simplepkg # feedback: rhatto at riseup.net | gpl # # Uses some functions from pkgtools, which license is: # # Copyright 1999 Patrick Volkerding, Moorhead, Minnesota, USA # Copyright 2001, 2002, 2003 Slackware Linux, Inc., Concord, California, USA # All rights reserved. # # Redistribution and use of this script, with or without modification, is # permitted provided that the following conditions are met: # # 1. Redistributions of this script must retain the above copyright # notice, this list of conditions and the following disclaimer. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # BASE_CONF="/etc/simplepkg" CONF="$BASE_CONF/simplepkg.conf" JAIL_LIST="$BASE_CONF/jailist" SIMPLARET="simplaret" # ----------------------------------------------- # pkgtool functions # ----------------------------------------------- function package_name { STRING=`basename $1 .tgz` # Check for old style package name with one segment: if [ "`echo $STRING | cut -f 1 -d -`" = "`echo $STRING | cut -f 2 -d -`" ]; then echo $STRING else # has more than one dash delimited segment # Count number of segments: INDEX=1 while [ ! "`echo $STRING | cut -f $INDEX -d -`" = "" ]; do INDEX=`expr $INDEX + 1` done INDEX=`expr $INDEX - 1` # don't include the null value # If we don't have four segments, return the old-style (or out of spec) package name: if [ "$INDEX" = "2" -o "$INDEX" = "3" ]; then echo $STRING else # we have four or more segments, so we'll consider this a new-style name: NAME=`expr $INDEX - 3` NAME="`echo $STRING | cut -f 1-$NAME -d -`" echo $NAME fi fi } # ----------------------------------------------- # package info functions # ----------------------------------------------- function package_version { # get VERSION from a package name local file pack version file="`basename $1`" pack="`package_name $1`" version="`echo $file | sed -e "s/^$pack-//" | cut -d "-" -f 1`" echo $version } function package_arch { # get ARCH from a package name local file pack arch file="`basename $1`" pack="`package_name $1`" arch="`echo $file | sed -e "s/^$pack-//" | cut -d "-" -f 2`" echo $arch } function package_build { # get BUILD from a package name local file pack build file="`basename $1 .tgz`" pack="`package_name $1`" build="`echo $file | sed -e "s/^$pack-//" | cut -d "-" -f 3`" echo $build } # ----------------------------------------------- # package administrative functions # ----------------------------------------------- function install_packages { local check installed unable_to_install root # check if is time to clean the local repository if [ "$SIMPLARET_CLEAN" == "1" ]; then ARCH=$ARCH VERSION=$VERSION $SIMPLARET --purge elif [ ! -z "$SIMPLARET_PURGE_WEEKS" ] && [ "$SIMPLARET_PURGE_WEEKS" != "0" ]; then ARCH=$ARCH VERSION=$VERSION $SIMPLARET --purge -w $SIMPLARET_PURGE_WEEKS fi root="$JAIL_ROOT/$server" # now tries to install each package listed in the template for pack in `cat $TEMPLATE | grep -v -e "^#" | cut -d : -f 1 | awk '{ print $1 }'`; do # try to install the package ROOT=/$root ARCH=$ARCH VERSION=$VERSION $SIMPLARET --install $pack --skip-checks # check if the package was installed pack="`echo $pack | sed -e 's/\+/\\\+/'`" installed=`eval "ls /$root/var/log/packages/ | egrep -E '^$pack-[^-]+-[^-]+-[^-]+$'"` check=$? if [ ! -z "$installed" ] && [ "$check" == "0" ]; then # the package is installed if [ ! -z "$SIMPLARET_DELETE_DURING" ] && [ "$SIMPLARET_DELETE_DURING" != "0" ]; then SILENT=1 ARCH=$ARCH VERSION=$VERSION $SIMPLARET --purge fi else unable_to_install="$unable_to_install\n\t$pack" fi done # purge packages, if needed if [ "$SIMPLARET_DELETE_DOWN" == "1" ]; then ARCH=$ARCH VERSION=$VERSION $SIMPLARET --purge fi if [ ! -z "$unable_to_install" ]; then echo "mkjail was unable to install the following packages on $root:" echo -e "$unable_to_install" fi } function remove_packages { for pack in `cat $TEMPLATE | grep -v -e "^#" | cut -d : -f 1`; do ROOT=/$JAIL_ROOT/$server removepkg $pack done } # ----------------------------------------------- # config file functions # ----------------------------------------------- function eval_parameter { # usage: eval $1 parameter from $CONF # return the evaluated parameter if available or $2 $3 ... $n if grep -qe "^$1=" $CONF; then grep -e "^$1=" $CONF | cut -d = -f 2 | sed -e 's/"//g' -e "s/'//g" | sed -e 's/ *#.*$//' else shift echo $* fi } function eval_boolean_parameter { # get a boolean parameter from the configuration local value # get the value value="`eval_parameter $1 $2`" # force case insensitiveness value="`echo $value | tr '[:upper:]' '[:lower:]'`" # convert it to wheter 0 or 1 if [ "$value" == "yes" ] || [ "$value" == "1" ]; then echo 1 else echo 0 fi } function eval_config { # simplepkg config file evaluation # usage: eval_config [-u] if [ -f "$CONF" ]; then DEFAULT_ARCH="`eval_parameter DEFAULT_ARCH $(default_arch)`" DEFAULT_VERSION="`eval_parameter DEFAULT_VERSION $(default_version)`" STORAGE="`eval_parameter STORAGE /var/simplaret/packages`" JAIL_ROOT="`eval_parameter JAIL_ROOT /vservers`" PATCHES_DIR="`eval_parameter PATCHES_DIR /var/simplaret/patches`" ROOT_PRIORITY="`eval_parameter ROOT_PRIORITY patches slackware extra testing pasture`" REPOS_PRIORITY="`eval_parameter REPOS_PRIORITY patches slackware extra testing pasture`" SIMPLARET_PURGE_WEEKS="`eval_parameter SIMPLARET_PURGE_WEEKS 0`" FTP_TOOL="`eval_parameter FTP_TOOL curl`" HTTP_TOOL="`eval_parameter HTTP_TOOL curl`" CONNECT_TIMEOUT="`eval_parameter CONNECT_TIMEOUT 0`" TEMPLATE_FOLDER="`eval_parameter TEMPLATE_BASE /etc/simplepkg/templates`" TEMPLATE_STORAGE_STYLE="`eval_parameter TEMPLATE_STORAGE_STYLE own-folder`" SIMPLARET_CLEAN="`eval_boolean_parameter SIMPLARET_CLEAN 1`" SIMPLARET_DELETE_DOWN="`eval_boolean_parameter SIMPLARET_DELETE_DOWN 1`" SIMPLARET_UPDATE="`eval_boolean_parameter SIMPLARET_UPDATE 0`" SIMPLARET_DELETE_DURING="`eval_boolean_parameter SIMPLARET_DELETE_DURING 0`" SIMPLARET_PURGE_PATCHES="`eval_boolean_parameter SIMPLARET_PURGE_PATCHES 1`" SIMPLARET_DOWNLOAD_FROM_NEXT_REPO="`eval_boolean_parameter SIMPLARET_DOWNLOAD_FROM_NEXT_REPO 1`" PASSIVE_FTP="`eval_boolean_parameter PASSIVE_FTP 0`" WARNING="`eval_boolean_parameter WARNING 0`" SIGNATURE_CHECKING="`eval_boolean_parameter SIGNATURE_CHECKING 0`" DEPENDENCY_CHECKING="`eval_boolean_parameter DEPENDENCY_CHECKING 1`" TEMPLATES_UNDER_SVN="`eval_boolean_parameter TEMPLATES_UNDER_SVN 0`" ADD_TO_JAIL_LIST="`eval_boolean_parameter ADD_TO_JAIL_LIST 1`" # Enabling this option (i.e, setting to "1" or "yes"), simplaret will # donwload even # already applied patches, a good option when you plan # to keep local copies of all needed patches for your system DOWNLOAD_EVEN_APPLIED_PATCHES="`eval_boolean_parameter DOWNLOAD_EVEN_APPLIED_PATCHES 0`" # Enabling this option, jail-upgrade will look at your # standard repositories for new packages; if it find a package # with different version of your current installed package and # also this package isnt in the packages folder, then the new # package is apllied; if in doubt, just say no or leave blank. CONSIDER_ALL_PACKAGES_AS_PATCHES="`eval_boolean_parameter CONSIDER_ALL_PACKAGES_AS_PATCHES 0`" # Enabling this option (i.e, setting to "1" or "yes"), simplaret will # store patches it finds on ROOT repositories on # # $PATCHES_DIR/$ARCH/$VERSION/root-$repository_name. # # By default this option is turned off because it breaks the standard # way to store packages and can cause some confusion, but its an useful # feature if you like to see all patches apart from common packages and/or # stored in the same tree. STORE_ROOT_PATCHES_ON_PATCHES_DIR="`eval_boolean_parameter STORE_ROOT_PATCHES_ON_PATCHES_DIR 0`" # now we place "patches" on the top of ROOT_PRIORITY ROOT_PRIORITY="patches `echo $ROOT_PRIORITY | sed -e 's/patches//'`" else echo $1 error: config file $CONFIG not found exit 1 fi if [ ! -d "$STORAGE" ]; then mkdir -p $STORAGE fi if [ ! -d "$PATCHES_DIR" ]; then mkdir -p $PATCHES_DIR fi if [ -z "$ARCH" ]; then ARCH="$DEFAULT_ARCH" fi if [ -z "$VERSION" ]; then VERSION="$DEFAULT_VERSION" fi if [ "$FTP_TOOL" != "wget" ] && [ "$FTP_TOOL" != "curl" ] && [ "$FTP_TOOL" != "ncftpget" ]; then echo "$1 configuration error: invalid value $FTP_TOOL for config parameter FTP_TOOL" echo "$1 assuming value \"curl\" for variable FTP_TOOL" FTP_TOOL="curl" fi if [ "$HTTP_TOOL" != "wget" ] && [ "$HTTP_TOOL" != "curl" ]; then echo "$1 configuration error: invalid value $HTTP_TOOL for config parameter HTTP_TOOL" echo "$1 assuming value \"curl\" for variable HTTP_TOOL" HTTP_TOOL="curl" fi if which $SIMPLARET &> /dev/null; then if [ "$SIMPLARET_UPDATE" == "1" ]; then if [ "$2" == "-u" ]; then ARCH=$ARCH VERSION=$VERSION $SIMPLARET --update fi fi else echo "$SIMPLARET not found, please install it before run $0" fi if [ "$TEMPLATE_STORAGE_STYLE" != "simplepkg-folder" ] && \ [ "$TEMPLATE_STORAGE_STYLE" != "templates-folder" ] && \ [ "$TEMPLATE_STORAGE_STYLE" != "own-folder" ]; then TEMPLATE_STORAGE_STYLE="own-folder" fi if [ ! -z "$ROOT" ]; then JAIL_ROOT="$ROOT" fi } # ----------------------------------------------- # arch and version functions # ----------------------------------------------- function default_version { # get version from /etc/slackware-version if [ -f "$1/etc/slackware-version" ]; then cat $1/etc/slackware-version | awk '{ print $2 }' | sed -e 's/.0$//' else echo "none" fi } function default_arch { # get arch from /etc/slackware-version local arch arch="`cat $1/etc/slackware-version | awk '{ print $3 }' | sed -e 's/(//' -e 's/)//'`" if [ -z "$arch" ]; then echo i386 else echo $arch fi } # ----------------------------------------------- # template functions # ----------------------------------------------- function search_default_template { if [ -e "$BASE_CONF/default.template" ]; then TEMPLATE_BASE="$BASE_CONF/default" echo $BASENAME using default template elif [ -e "$TEMPLATE_FOLDER/default.template" ]; then TEMPLATE_BASE="$TEMPLATE_FOLDER/default" echo $BASENAME: using default template elif [ -e "$TEMPLATE_FOLDER/default/default.template" ]; then TEMPLATE_BASE="$TEMPLATE_FOLDER/default/default" echo $BASENAME: using default template elif [ -e "$BASE_CONF/defaults/templates/default/default.template" ]; then TEMPLATE_BASE="$BASE_CONF/defaults/templates/default" echo $BASENAME using default template else echo $BASENAME: error: default template not found echo $BASENAME: please create a template using templatepkg return 1 fi } function search_template { # determine the template to be used # usage: search-template [--new | --update] # # templates can be stored either on # # - $BASE_CONF/template_name.template # - $TEMPLATE_FOLDER/template_name.template # - $TEMPLATE_FOLDER/template_name/template_name.template # # also, there's a folder for "oficial" simplepkg templates, # $BASE_CONF/defaults/templates/ and you can override any template # in the default folder by placing a template with the same name # in the template storage folders # if [ -f "$BASE_CONF/$1.template" ]; then TEMPLATE_BASE="$BASE_CONF/$1" elif [ -f "$TEMPLATE_FOLDER/$1.template" ]; then TEMPLATE_BASE="$TEMPLATE_FOLDER/$1" elif [ -f "$TEMPLATE_FOLDER/$1/$1.template" ]; then TEMPLATE_BASE="$TEMPLATE_FOLDER/$1/$1" elif [ -f "$BASE_CONF/defaults/templates/$1/$1.template" ] && \ [ "$2" != "--update" ]; then TEMPLATE_BASE="$BASE_CONF/defaults/templates/$1/$1" else if [ "$2" == "--new" ]; then # we need to return the path for a new template if [ "$TEMPLATE_STORAGE_STYLE" == "simplepkg-folder" ]; then TEMPLATE_BASE="$BASE_CONF/$1" elif [ "$TEMPLATE_STORAGE_STYLE" == "templates-folder" ]; then TEMPLATE_BASE="$TEMPLATE_FOLDER/$1" else TEMPLATE_BASE="$TEMPLATE_FOLDER/$1/$1" fi elif [ "$2" == "--update" ]; then return 1 else echo $BASENAME: template $1 not found search_default_template fi fi } # ----------------------------------------------- # unix permission functions # ----------------------------------------------- function numeric_perm { # get the numeric permission of a file # usage: numeric_perm # just a bit of forbidden secrets if [ -a "$1" ]; then ls -lnd $1 | awk '{ print $1 }' | \ sed -e 's/^.//' -e 's/r/4/g' -e 's/w/2/g' -e 's/x/1/g' \ -e 's/-/0/g' -e 's/\(.\)\(.\)\(.\)/\1+\2+\3/g' | \ fold -w5 | bc -l | xargs | sed -e 's/ //g' fi } function get_owner { # get the numeric owner for a file # usage: get_owner if [ -a "$1" ]; then ls -lnd $1 | awk '{ print $3 }' fi } function get_group { # get the numeric group for a file # usage: get_group if [ -a "$1" ]; then ls -lnd $1 | awk '{ print $4 }' fi } # ----------------------------------------------- # subversion functions # ----------------------------------------------- function use_svn { # check if svn usage is enabled if [ "$TEMPLATES_UNDER_SVN" == "1" ] && \ [ "$TEMPLATE_STORAGE_STYLE" == "own-folder" ]; then return 0 else return 1 fi } function svn_check { # check if a file is under svn # usage: svn_check local cwd folder cwd="`pwd`" folder="`dirname $1`" if [ -d "$folder/.svn" ]; then cd $folder if [ "`svn status $1 | awk '{ print $1 }'`" == "?" ]; then return 1 else return 0 fi cd $cwd else return 1 fi } # ----------------------------------------------- # update jail functions # ----------------------------------------------- function update_template_files { # update template files from svn # usage: update_template_files if use_svn && [ -d "$TEMPLATE_BASE.d/.svn" ]; then echo Checking out last template revision from svn... cd `dirname $TEMPLATE_BASE` svn update fi } function copy_template_files { # copy template files into jail # usage: copy_template_files if [ -d "$1" ]; then if [ -d "$TEMPLATE_BASE.d" ]; then echo "Copying template files to $1..." if use_svn && [ -d "$TEMPLATE_BASE.d/.svn" ]; then rsync -av --exclude=.svn $TEMPLATE_BASE.d/ $1/ else rsync -av $TEMPLATE_BASE.d/ $1/ fi fi fi } function set_jail_perms { # set template file permissions under a jail # usage: set_jail_perms if [ -s "$TEMPLATE_BASE.perms" ]; then echo Setting jail $1 permissions... cat $TEMPLATE_BASE.perms | while read entry; do file="`echo $entry | cut -d ";" -f 1`" if [ -e "$TEMPLATE_BASE.d/$file" ] && [ -a "$1/$file" ]; then owner="`echo $entry | cut -d ";" -f 2`" group="`echo $entry | cut -d ";" -f 3`" perms="`echo $entry | cut -d ";" -f 4`" chmod $perms $1/$file chown $owner:$group $1/$file fi done fi } # ----------------------------------------------- # repository build functions # ----------------------------------------------- function svn_add_meta { find . -name '*meta' -exec svn add {} 2> /dev/null \; } function gen_filelist { # generate FILELIST.TXT # usage: gen_filelist find . -type f -name '*.tgz' -follow -print | sort | tr '\n' '\0' | \ xargs -0r ls -ldL --time-style=long-iso > FILELIST.TXT echo "Created new FILELIST.TXT" } function gen_patches_filelist { # generate FILE_LIST # usage: gen_patches_filelist if [ ! -z "$1" ] && [ -d "$1" ]; then cwd="`pwd`" cd $1 for file in `find | grep -e ".tgz$"`; do ls -l $file; done > FILE_LIST cd $cwd if [ "$1" == "." ]; then echo "Created new FILE_LIST" else echo "Created new $1/FILE_LIST" fi fi } function gen_packages_txt { # generate PACKAGES.TXT # usage: gen_packages_txt if [ ! -z "$1" ] && [ -d "$1" ]; then cwd="`pwd`" cd $1 echo '' > PACKAGES.TXT find . -type f -name '*.meta' -exec cat {} \; >> PACKAGES.TXT cat PACKAGES.TXT | gzip -9 -c - > PACKAGES.TXT.gz cd $cwd if [ "$1" == "." ]; then echo "Created new PACKAGES.TXT and PACKAGES.TXT.gz" else echo "Created new $1/PACKAGES.TXT and $1/PACKAGES.TXT.gz" fi fi } function gen_md5_checksums { # generate CHECKSUMS.md5 # usage: gen_md5_checksums if [ -d "$1" ]; then cwd="`pwd`" cd $1 echo '' > CHECKSUMS.md5 find . -type f -name '*.tgz' -exec md5sum {} \; >> CHECKSUMS.md5 cat CHECKSUMS.md5 | gzip -9 -c - > CHECKSUMS.md5.gz cd $cwd if [ "$1" == "." ]; then echo "Created new CHECKSUMS.md5 and CHECKSUMS.md5.gz" else echo "Created new $1/CHECKSUMS.md5 and $1/CHECKSUMS.md5.gz" fi fi } function gen_meta { # generate metafiles # usage: gen_meta if [ ! -f $1 ]; then echo "File not found: $1" exit 1; else echo "Processing $1" fi if [ "`echo $1|grep -E '(.*{1,})\-(.*[\.\-].*[\.\-].*).tgz[ ]{0,}$'`" == "" ]; then return; fi NAME=$(echo $1|sed -re "s/(.*\/)(.*.tgz)$/\2/") LOCATION=$(echo $1|sed -re "s/(.*)\/(.*.tgz)$/\1/") SIZE=$( expr `gunzip -l $1 | tail -n 1|awk '{print $1}'` / 1024 ) USIZE=$( expr `gunzip -l $1 | tail -n 1|awk '{print $2}'` / 1024 ) REQUIRED=$(tar xzfO $1 install/slack-required 2>/dev/null|xargs -r -iZ echo -n "Z,"|sed -e "s/,$//") CONFLICTS=$(tar xzfO $1 install/slack-conflicts 2>/dev/null|xargs -r -iZ echo -n "Z,"|sed -e "s/,$//") SUGGESTS=$(tar xzfO $1 install/slack-suggests 2>/dev/null|xargs -r ) METAFILE=${NAME%tgz}meta echo "PACKAGE NAME: $NAME" > $LOCATION/$METAFILE if [ -n "$DL_URL" ]; then echo "PACKAGE MIRROR: $DL_URL" >> $LOCATION/$METAFILE fi echo "PACKAGE LOCATION: $LOCATION" >> $LOCATION/$METAFILE echo "PACKAGE SIZE (compressed): $SIZE K" >> $LOCATION/$METAFILE echo "PACKAGE SIZE (uncompressed): $USIZE K" >> $LOCATION/$METAFILE echo "PACKAGE REQUIRED: $REQUIRED" >> $LOCATION/$METAFILE echo "PACKAGE CONFLICTS: $CONFLICTS" >> $LOCATION/$METAFILE echo "PACKAGE SUGGESTS: $SUGGESTS" >> $LOCATION/$METAFILE echo "PACKAGE DESCRIPTION:" >> $LOCATION/$METAFILE tar xzfO $1 install/slack-desc | grep -E '\w+\:'|grep -v '^#' >> $LOCATION/$METAFILE echo "" >> $LOCATION/$METAFILE } # ----------------------------------------------- # misc functions # ----------------------------------------------- function slash { # remove additional slashes echo $* | sed -e 's/\/\+/\//g' }