# $Id: functions,v 1.14 2004/01/16 17:59:12 ensc Exp $	--*- sh -*--

# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
#  
# 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; version 2 of the License.
#  
# 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.

_VS_NEWLINE='
'
declare -r _VS_NEWLINE=${_VS_NEWLINE:0-1}

function findObject
{
    local mod=$1
    local var=$2
    local file=
    local i=X
    shift 2
    
    for i; do
	test "$i"        || continue
	test ! $mod "$i" || { file=$i; break; }
    done

    test -z "$i" -o "$file" || {
	echo "Can not find file for '$var'; aborting"
	exit 1
    } >&2

    eval "$var=\"$file\""
}

function findFile
{
    findObject -f "$@"
}

function findDir
{
    findObject -d "$@"
}

function findAndCopy
{
    local dst=$1
    test ! -s "$dst"         || return 0
    
    local tmp
    shift
    findFile tmp "$@"

    test "$tmp" -a -s "$tmp" || return 0
    cp -af "$tmp" "$dst"
}

function getPhysicalDir
{
    ( set -P && cd "$1" && pwd )
}

function _pkgMountBindDir()
{
    test "$1" != "$2" || return 0

    mount -n --bind "$1" "$2"
}

function _pkgSetVarsBase
{
    case "$vserver" in
	./*|/*)
	    if test -d "$vserver/vdir"; then
		BASEDIR=$vserver
		VDIR=$(getPhysicalDir "$vserver/vdir")
		
		PKGDIR=$BASEDIR/apps/pkgmgmt
		test -d "$PKGDIR" || {
		    echo "Can not find configuration-directory for package-managment tools"
		    exit 1
		}
		findDir EXECDIR      $PKGDIR/execdir     /
	    else
		VDIR=$(getPhysicalDir "$vserver")
		PKGDIR=
	    fi
	    ;;
        *)
    	    BASEDIR=$CONFDIR/$vserver
    	    test -d "$BASEDIR" || {
    	        echo "Can not find configuration-directory"
    	        exit 1
    	    }
    	    
    	    VDIR=$BASEDIR/vdir
    	    test -d "$VDIR"   || VDIR=/vservers/$vserver
	    VDIR=$(getPhysicalDir "$VDIR")
    	    
    	    PKGDIR=$BASEDIR/apps/pkgmgmt
    	    test -d "$PKGDIR" || {
    	        echo "Can not find configuration-directory for package-managment tools"
    	        exit 1
    	    }

	    findDir EXECDIR      $PKGDIR/execdir     /

	    ;;
    esac

    if test -z "$WORKAROUND_106057"; then
	_rpmdb_mntpoint=/dev
    else
	_rpmdb_mntpoint=/.rpmdb
    fi
}

function _pkgSetVarsRPM
{
    if test "$PKGDIR"; then
	findDir RPMETCDIR    $PKGDIR/rpmetc      $PKGDIR/base/rpm/etc       /etc/rpm
	findDir RPMSTATEDIR  $PKGDIR/rpmstate    $PKGDIR/base/rpm/state

	findDir RPMLIBDIR    $PKGDIR/rpmlib	 /

    else
	findDir RPMETCDIR    "$VDIR"/etc/rpm     /etc/rpm
	findDir RPMSTATEDIR  "$VDIR"/var/lib/rpm
	RPMLIBDIR=/
    fi
    
    RPMSTATEDIR=$(getPhysicalDir "$RPMSTATEDIR")
    RPMETCDIR=$(getPhysicalDir "$RPMETCDIR")
}

function _pkgSetVarsApt
{
    if test "$PKGDIR"; then
	findDir APTETCDIR    $PKGDIR/aptetc      $PKGDIR/base/apt/etc       /etc/apt
	findDir APTSTATEDIR  $PKGDIR/aptstate    $PKGDIR/base/apt/state
	findDir APTCACHEDIR  $PKGDIR/aptcache    $PKGDIR/base/apt/cache
	findDir APTARCHIVDIR $PKGDIR/aptarchives $PKGDIR/base/apt/archives  /var/cache/apt/archives
    else
	findDir APTETCDIR    "$VDIR"/etc/apt       	/etc/apt
	findDir APTSTATEDIR  "$VDIR"/var/state/apt
	findDir APTCACHEDIR  "$VDIR"/var/cache/apt
	findDir APTARCHIVDIR "$VDIR"/var/cache/apt/archives /var/cache/apt/archives
    fi

    findFile APT_CONFIG "$APTETCDIR"/apt.conf ""
    test -z "$APT_CONFIG" || export APT_CONFIG
}

function _pkgMountBase
{
    :
}

function _pkgMountApt
{
    :
}

function _pkgMountRPM
{
    _pkgMountBindDir "$RPMETCDIR" /etc/rpm
    test "$RPMLIBDIR" = "/" || _pkgMountBindDir "$RPMLIBDIR" /usr/lib/rpm

    "$_SECURE_MOUNT" --chroot "$VDIR" -n --secure --bind "$RPMSTATEDIR" "$_rpmdb_mntpoint"
    test -z "$WORKAROUND_106057" || mount -n --bind "$RPMSTATEDIR" "$_rpmdb_mntpoint"
}

function _pkgSetEnvBase
{
    test "$EXECDIR"   = "/" || {
	PATH=$EXECDIR:$PATH
	LD_LIBRARY_PATH=$EXECDIR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
    }

    export PATH LD_LIBRARY_PATH
}

function _pkgSetEnvApt
{
    :
}

function _pkgSetEnvRPM
{
    CUR_VSERVER=$vserver
    RPM_FAKE_NAMESPACE_MOUNTS=$_rpmdb_mntpoint
    RPM_BINARY=$_VRPM_PRELOAD

    export CUR_VSERVER RPM_FAKE_NAMESPACE_MOUNTS RPM_BINARY
}

function pkgInit
{
    local i
    local vserver=$1
    shift
    
    _pkgSetVarsBase
    for i; do
	case "$i" in
	    rpm)	_pkgSetVarsRPM;;
	    apt)	_pkgSetVarsApt;;
	    *)		echo "Unknown packaging flavor"; exit 1;;
	esac
    done

    _pkgMountBase
    for i; do
	case "$i" in
	    rpm)	_pkgMountRPM;;
	    apt)	_pkgMountApt;;
	esac
    done

    _pkgSetEnvBase
    for i; do
	case "$i" in
	    rpm)	_pkgSetEnvRPM;;
	    apt)	_pkgSetEnvApt;;
	esac
    done

    _PKG_FLAVORS="$@"
    _PKG_VSERVER=$vserver
}

function getAllVservers
{
    local i
    declare -a _tmp=()

    for i in $CONFDIR/*; do
	test   -d "$i"          || continue
	test ! -e "$i"/disabled || continue
	test   -d "$i"/vdir     || continue
	case "$i" in
	    *.~*~) continue;;
	esac

	_tmp=( "${_tmp[@]}" "${i##$CONFDIR/}")
    done

    eval $1='( "${_tmp[@]}" )'
}

## Usage: getVserverCtx <vdir> <result-varname> [<procnumber-varname> [<do-cleanup>]]
function getVserverStatus
{
    test -r "$1"/run || return 1

    local _ctx
    read _ctx <"$1"/run
    eval "$2"=\$_ctx

    test "$3"        || return 0
    local _tmp=$($_VPS ax | $_AWK '{print $2}' | $_GREP -x "$_ctx" | $_WC -l )
    eval "$3"=\$_tmp

    test "$4" -a $_tmp = 0 || return 0
    _tmp=$(readlink "$1/run")
    test "$_tmp"           || return 1
    rm -f "$_tmp"
    return 0
}

## Usage: isCtxRunning <ctx>
function isCtxRunning
{
    local _tmp=$($_VPS ax | $_AWK '{print $2}' | $_GREP -x "$1" | $_WC -l )
    test $_tmp -gt 0
}

## Usage: isVserverRunning <vdir> [<ctx-varname>]
function isVserverRunning
{
    local ctx procnum

    getVserverStatus "$1" ctx procnum 1 || return 1
    test $procnum != 0                  || return 1
    test -z "$2" || eval "$2"=\$ctx
    return 0
}

## Called as 'getFileValue <varname> <filename>'
function getFileValue
{
    test -r "$2" || return 0
    eval read "$1" <"$2"
}

## Called as 'getFileArray <varname> <filename>'
function getFileArray
{
    test -r "$2" || return 0
    
    local IFS=$_VS_NEWLINE
    eval "$1"='( $(< "$2") )'
}

function checkComponents
{
    local	i
    local	msg=$1
    local	x_failed=

    shift
    
    for i; do
	local failed=
	case "$i" in
	    core)	test -x "$_CHBIND"           || failed=1;;
	    build)	test -x "$_VSERVER_BUILD"    || failed=1;;
	    sysv)	test -x "$INITRDDIR/vserver" || failed=1;;
	    devel)	test -d "$INCLUDEDIR/vserver.h" || failed=1;;
	    *)		echo "Unknown component '$i'"
			return false
			;;
	esac

	test -z "$failed" || {
	    echo "$msg: $i"
	    x_failed=1
	}
    done

    test -z "$x_failed"
}
