applied http://savannah.nongnu.org/patch/?func=detailitem&item_id=4814
[util-vserver.git] / util-vserver / scripts / pkgmgmt
index 9a644b3..397eca2 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/bash
 # $Id$
 
-# Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# Copyright (C) 2004,2005 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
@@ -24,7 +24,7 @@ test -e "$UTIL_VSERVER_VARS" || {
 . "$UTIL_VSERVER_VARS"
 . "$_LIB_FUNCTIONS"
 . "$_LIB_VSERVER_BUILD_FUNCTIONS_PKGMGMT"
-. "$PKGLIBDIR/vserver.functions"
+. "$__PKGLIBDIR/vserver.functions"
 
 function showHelp()
 {
@@ -41,7 +41,7 @@ function showVersion()
 vpkg $PACKAGE_VERSION -- shows information about packages in vservers
 This program is part of $PACKAGE_STRING
 
-Copyright (C) 2004 Enrico Scholz
+Copyright (C) 2004,2005 Enrico Scholz
 This program is free software; you may redistribute it under the terms of
 the GNU General Public License.  This program has absolutely no warranty."
     exit 0
@@ -60,7 +60,7 @@ function init()
 function _createDirs()
 {
     for i; do
-       test "$i" || continue
+       test -n "$i" || continue
        mkdir -p -m755 "$i"
     done
 }
@@ -86,22 +86,41 @@ function _copySecureRev()
     ( cd "$dstdir" && tar xf - )
 }
 
+## Usage: _substFile <filename> <sed-expression>
+function _substFile()
+{
+    local file=$1
+    local expr=$2
+    
+    $_CHROOT_SH testfile "$file" || return 0
+
+    local tmp=$($_MKTEMP /tmp/pkgmgmt_subst.XXXXXX)
+    trap "$_RM -f $tmp" EXIT
+
+    $_CHROOT_SH cat "$file" | \
+       $_SED -e "$expr" >$tmp
+
+    $_CHROOT_SH cat "$file" | $_CMP -s $tmp - || \
+       $_CHROOT_SH truncate "$file" <$tmp
+
+    $_RM -f $tmp
+}
+
 function _hashAuto()
 {
+    local file=$1
     local hash=$2
-    local dir=$(dirname "$1")
-    local file=$(basename "$1")
 
-    $_EXEC_CD "$dir" "$(which test)" "$file" || return 0
+    $_CHROOT_SH testfile "$file" || return 0
     
     local tmp=$($_MKTEMP /tmp/apt.conf.XXXXXX)
     trap "$_RM -f $tmp" EXIT
 
-    $_EXEC_CD "$dir" $_CAT "$file" | \
+    $_CHROOT_SH cat "$file" | \
        $_SED -e "s|^\([^$hash].*@autogenerated@\)|$hash$hash\1|" >$tmp
 
-    $_CAT $tmp | $_EXEC_CD "$dir" "$(which cmp)" -s - "$file" || \
-       $_CHROOT_CAT "$1" <$tmp
+    $_CHROOT_SH cat "$file" | $_CMP -s $tmp - || \
+       $_CHROOT_SH truncate "$file" <$tmp
 
     $_RM -f $tmp
 }
@@ -134,11 +153,12 @@ function _mountFilesystemsInternal()
 
 function _mountFilesystems()
 {
-    local cfgdir=$($_VSERVER_INFO "$1" CFGDIR) || {
+    local cfgdir
+    cfgdir=$($_VSERVER_INFO "$1" CFGDIR) || {
        echo "Can not determine configuration directory for '$1'; ..." >&2
        return 1
     }
-    test "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
+    test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
     
     _mountFilesystemsInternal "$cfgdir"/fstab       $_CHBIND "${CHBIND_OPTS[@]}" || return 1
     _mountFilesystemsInternal "$cfgdir"/fstab.local $_CHBIND "${CHBIND_OPTS[@]}" || return 1
@@ -146,20 +166,66 @@ function _mountFilesystems()
 
 function _umountFilesystems()
 {
-    local cfgdir=$($_VSERVER_INFO "$1" CFGDIR) || {
+    local cfgdir
+    cfgdir=$($_VSERVER_INFO "$1" CFGDIR) || {
        echo "Can not determine configuration directory for '$1'; ..." >&2
        return 1
     }
     local vdir=$cfgdir/vdir
     local is_ok=1
-    test "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
+    test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
 
     pushd "$vdir/" >/dev/null || return 1
        _umountVserverInternal  "$cfgdir"/fstab.local                              || is_ok=
        _umountVserverInternal  "$cfgdir"/fstab       $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
     popd >/dev/null           || return 1
     
-    test "$is_ok"
+    test -n "$is_ok"
+}
+
+# Usage: verifyInternalPackages <vserver> <style>
+function verifyInternalPackages()
+{
+    local pkgs res=0
+    local ERR="\
+The following errors occured while trying to internalize the
+packagemanagement:
+"
+    
+    case $2 in
+       (RH)    pkgs=$(vrpm "$1" -- -q --qf '---%{NAME}---\n' rpm apt yum "${YUM_RELEASEPKGS[@]}")
+               hasSubstring "$pkgs" ---rpm--- || {
+                   warning "$ERR
+* The vserver does not seem to have the 'rpm' package which is required
+  for internal package management. It is suggested to install it before
+  continuing."
+                   res=1
+                   ERR=
+               }
+               
+               hasSubstring "$pkgs"  ---apt--- ---yum--- || {
+                   warning "$ERR
+* The vserver does not seem to have a depsolver like 'apt' or 'yum'
+  installed. It is suggested to install such a program before setting
+  up internal package management."
+                   res=1
+                   ERR=
+               }
+
+               test -n "$have_apt" || test -z "$have_yum"   || \
+               hasSubstring "$pkgs" "${YUM_RELEASEPKGS[@]}" || {
+                   warning "$ERR
+* yum requires a special package which describes the version of the
+  distribution. Such a package could not be found within the vserver
+  so please install it before continuing. Usually, this package is
+  named 'redhat-release' of 'fedora-release'."
+                   res=1
+                   ERR=
+               }
+               ;;
+    esac
+
+    return $res
 }
 
 function processVserver_RH()
@@ -175,7 +241,9 @@ function processVserver_RH()
 
     ## Figure out the environment....
     have_apt=1
+    have_yum=1
     pkgmgmt.isAptAvailable "$cfgdir" "$vdir" "$is_internalize" || have_apt=
+    pkgmgmt.isYumAvailable "$cfgdir" "$vdir" "$is_internalize" || have_yum=
 
     local APTETCDIR=
     local APTSTATEDIR=
@@ -186,7 +254,11 @@ function processVserver_RH()
 
     ## Create directories and assign variables where configuration
     ## can/will be found on the host
-    if test "$is_internalize"; then
+    if test -n "$is_internalize"; then
+       verifyInternalPackages "$vserver" RH || test -n "$IS_FORCE" ||
+           panic "
+Can not continue; use '--force' to override this check"
+    
        pushd "$vdir" >/dev/null
 
        test ! -L var/lib/rpm || {
@@ -205,7 +277,7 @@ function processVserver_RH()
        
        popd >/dev/null
        
-       if test "$have_apt"; then
+       if test -n "$have_apt"; then
            findDir APTETCDIR    "$cfgdir"/aptetc "$cfgdir"/base/apt/etc /etc/apt /
        fi
 
@@ -215,7 +287,7 @@ function processVserver_RH()
        mkdir -m755 -p "$cfgdir"
        local need_base=
 
-       if test "$have_apt"; then
+       if test -n "$have_apt"; then
            findDir APTETCDIR    "$cfgdir"/aptetc      "$cfgdir"/base/apt/etc       /
            findDir APTSTATEDIR  "$cfgdir"/aptstate    "$cfgdir"/base/apt/state     /
            findDir APTCACHEDIR  "$cfgdir"/aptcache    "$cfgdir"/base/apt/cache     /
@@ -247,8 +319,8 @@ function processVserver_RH()
     fi
 
     ## Copy the files...
-    if test "$is_internalize"; then
-       if test "$have_apt"; then
+    if test -n "$is_internalize"; then
+       if test -n "$have_apt"; then
            _copySecure "$vdir" "$APTETCDIR" /etc/apt
            pushd "$vdir" >/dev/null
                _hashAuto /etc/apt/apt.conf '/'
@@ -258,18 +330,24 @@ function processVserver_RH()
        _copySecure "$vdir" "$RPMETCDIR"   /etc/rpm
        _copySecure "$vdir" "$RPMSTATEDIR" /var/lib/rpm
 
+       pushd "$vdir" >/dev/null
+           ## remove %_dbpath settings
+           _substFile /etc/rpm/macros '/^%_dbpath[ \t].*/D'
+       popd >/dev/null
     else
-       if test "$have_apt"; then
+       if test -n "$have_apt"; then
            _copySecureRev "$vdir" /etc/apt "$APTETCDIR"
            _unhashAuto "$APTETCDIR"/apt.conf '/'
        fi
 
        _copySecureRev "$vdir" /etc/rpm     "$RPMETCDIR"
        _copySecureRev "$vdir" /var/lib/rpm "$RPMSTATEDIR"
+
+       echo -e "%_dbpath\t\t$rpmdb_mntpoint" >>$RPMETCDIR/macros
     fi
 
     ## Cleanups...
-    if test "$is_internalize"; then
+    if test -n "$is_internalize"; then
        :
     else
        tmpdir=$($_MKTEMPDIR /var/tmp/pgmgmt.XXXXXX)
@@ -281,7 +359,7 @@ function processVserver_RH()
     fi
 
     ## Finish it...
-    if test "$is_internalize"; then
+    if test -n "$is_internalize"; then
        $_TOUCH "$cfgdir"/internal
     else
        $_RM -f "$cfgdir"/internal
@@ -293,7 +371,7 @@ function processVserver_Debian()
     local vserver=$1
     local is_internalize=$2
 
-    if test "$is_internalize"; then
+    if test -n "$is_internalize"; then
        echo $"Debian vservers should be internalized everytime; do not know how to handle '$vserver'" >&2
     else
        echo $"External packagemanagement is not supported for Debian vserver" >&2
@@ -346,12 +424,13 @@ function processVserver()
     _umountFilesystems "$vserver"       || return 1
 }
 
-tmp=$(getopt -o y --long debug,externalize,internalize,help,version -n "$0" -- "$@") || exit 1
+tmp=$(getopt -o y --long debug,externalize,internalize,help,version,force -n "$0" -- "$@") || exit 1
 eval set -- "$tmp"
 
 IS_EXTERNALIZE=
 IS_INTERNALIZE=
 IS_YES=
+IS_FORCE=
 
 while true; do
     case "$1" in
@@ -360,6 +439,7 @@ while true; do
        (--debug)       set -x;;
        (--externalize) IS_EXTERNALIZE=1;;
        (--internalize) IS_INTERNALIZE=1;;
+       (--force)       IS_FORCE=1;;
        (-y)            IS_YES=1;;
        (--)            shift; break;;
        (*)             echo $"vserver: internal error; arg=='$1'" >&2; exit 1;;
@@ -367,7 +447,7 @@ while true; do
     shift
 done
 
-test "$1" || {
+test -n "$1" || {
     echo $"No vserver specified; try '--help' for more information"
     exit 1
 } >&2