use $(LIBENSCVECTOR) instead of libensc_vector.a
[util-vserver.git] / util-vserver / scripts / pkgmgmt
1 #!/bin/bash
2 # $Id$
3
4 # Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
5 #  
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; version 2 of the License.
9 #  
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #  
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 : ${UTIL_VSERVER_VARS:=/usr/lib/util-vserver/util-vserver-vars}
20 test -e "$UTIL_VSERVER_VARS" || {
21     echo $"Can not find util-vserver installation (the file '$UTIL_VSERVER_VARS' would be expected); aborting..." >&2
22     exit 1
23 }
24 . "$UTIL_VSERVER_VARS"
25 . "$_LIB_FUNCTIONS"
26 . "$_LIB_VSERVER_BUILD_FUNCTIONS_PKGMGMT"
27 . "$__PKGLIBDIR/vserver.functions"
28
29 function showHelp()
30 {
31     echo \
32 $"Usage: $0 --externalize|--internalize [-y] [--] <vserver-name>
33
34 Report bugs to <$PACKAGE_BUGREPORT>."
35     exit 0
36 }
37
38 function showVersion()
39 {
40     echo $"\
41 vpkg $PACKAGE_VERSION -- shows information about packages in vservers
42 This program is part of $PACKAGE_STRING
43
44 Copyright (C) 2004 Enrico Scholz
45 This program is free software; you may redistribute it under the terms of
46 the GNU General Public License.  This program has absolutely no warranty."
47     exit 0
48 }
49
50 function init()
51 {
52     if test -z "$WORKAROUND_106057"; then
53         rpmdb_mntpoint=/dev
54     else
55         rpmdb_mntpoint=/.rpmdb
56     fi
57     pkgmgmt.initVariables
58 }
59
60 function _createDirs()
61 {
62     for i; do
63         test -n "$i" || continue
64         mkdir -p -m755 "$i"
65     done
66 }
67
68 function _copySecure()
69 {
70     local chroot=$1
71     local srcdir=$2
72     local dstdir=$3
73
74     
75     ( cd "$srcdir" && tar chf - '.' ) | \
76     ( cd "$chroot" && $_EXEC_CD "$dstdir" $_TAR xf - )
77 }
78
79 function _copySecureRev()
80 {
81     local chroot=$1
82     local srcdir=$2
83     local dstdir=$3
84
85     ( cd "$chroot" && $_EXEC_CD "$srcdir" $_TAR cf - '.' ) | \
86     ( cd "$dstdir" && tar xf - )
87 }
88
89 function _hashAuto()
90 {
91     local hash=$2
92     local dir=$(dirname "$1")
93     local file=$(basename "$1")
94
95     $_EXEC_CD "$dir" "$(which test)" "$file" || return 0
96     
97     local tmp=$($_MKTEMP /tmp/apt.conf.XXXXXX)
98     trap "$_RM -f $tmp" EXIT
99
100     $_EXEC_CD "$dir" $_CAT "$file" | \
101         $_SED -e "s|^\([^$hash].*@autogenerated@\)|$hash$hash\1|" >$tmp
102
103     $_CAT $tmp | $_EXEC_CD "$dir" "$(which cmp)" -s - "$file" || \
104         $_CHROOT_CAT "$1" <$tmp
105
106     $_RM -f $tmp
107 }
108
109 function _unhashAuto()
110 {
111     test -e "$1" || return 0
112
113     local hash=$2
114     local tmp=$($_MKTEMP /tmp/apt.conf.XXXXXX)
115     trap "$_RM -f $tmp" EXIT
116
117     $_SED -e "s|^$hash$hash\(.*@autogenerated@\)|\1|" "$1" >$tmp
118     $_CMP -s "$tmp" "$1" || \
119         $_CAT "$tmp" >"$1"
120
121     $_RM -f $tmp
122 }
123
124 function _mountFilesystemsInternal()
125 {
126     local fstab="$1"
127     test -e "$fstab" || return 0
128     shift
129
130     pushd "$vdir" >/dev/null
131     "$@" $_SECURE_MOUNT -n -a --chroot --fstab "$fstab"
132     popd >/dev/null
133 }
134
135 function _mountFilesystems()
136 {
137     local cfgdir
138     cfgdir=$($_VSERVER_INFO "$1" CFGDIR) || {
139         echo "Can not determine configuration directory for '$1'; ..." >&2
140         return 1
141     }
142     test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
143     
144     _mountFilesystemsInternal "$cfgdir"/fstab       $_CHBIND "${CHBIND_OPTS[@]}" || return 1
145     _mountFilesystemsInternal "$cfgdir"/fstab.local $_CHBIND "${CHBIND_OPTS[@]}" || return 1
146 }
147
148 function _umountFilesystems()
149 {
150     local cfgdir
151     cfgdir=$($_VSERVER_INFO "$1" CFGDIR) || {
152         echo "Can not determine configuration directory for '$1'; ..." >&2
153         return 1
154     }
155     local vdir=$cfgdir/vdir
156     local is_ok=1
157     test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
158
159     pushd "$vdir/" >/dev/null || return 1
160         _umountVserverInternal  "$cfgdir"/fstab.local                              || is_ok=
161         _umountVserverInternal  "$cfgdir"/fstab       $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
162     popd >/dev/null           || return 1
163     
164     test -n "$is_ok"
165 }
166
167 function processVserver_RH()
168 {
169     local vserver=$1
170     local is_internalize=$2
171     local have_apt
172     local cfgdir
173     local i
174
175     cfgdir=$($_VSERVER_INFO "$vserver" APPDIR pkgmgmt) || \
176     cfgdir=$($_VSERVER_INFO "$vserver" APPDIR)/pkgmgmt
177
178     ## Figure out the environment....
179     have_apt=1
180     pkgmgmt.isAptAvailable "$cfgdir" "$vdir" "$is_internalize" || have_apt=
181
182     local APTETCDIR=
183     local APTSTATEDIR=
184     local APTCACHEDIR=
185     local APTARCHIVDIR=
186     local RPMETCDIR=
187     local RPMSTATEDIR=
188
189     ## Create directories and assign variables where configuration
190     ## can/will be found on the host
191     if test -n "$is_internalize"; then
192         pushd "$vdir" >/dev/null
193
194         test ! -L var/lib/rpm || {
195             $_EXEC_CD /var/lib $_RM            rpm &&
196             $_EXEC_CD /var/lib $_MKDIR -m755   rpm &&
197             $_EXEC_CD /var/lib $_CHOWN rpm:rpm rpm ||
198             :
199         } </dev/null 2>/dev/null
200
201         for i in var/cache/apt/{,archives/{,partial},genpkglist,gensrclist} \
202                  var/state/{,apt/{,lists/{,partial}}} \
203                  etc/apt etc/rpm; do
204             test -d "$i" ||
205                 $_EXEC_CD /$(dirname "$i") $_MKDIR -m755 $(basename "$i") || :
206         done #2>/dev/null
207         
208         popd >/dev/null
209         
210         if test -n "$have_apt"; then
211             findDir APTETCDIR    "$cfgdir"/aptetc "$cfgdir"/base/apt/etc /etc/apt /
212         fi
213
214         findDir RPMETCDIR   "$cfgdir"/rpmetc   "$cfgdir"/base/rpm/etc    /etc/rpm /
215         findDir RPMSTATEDIR "$cfgdir"/rpmstate "$cfgdir"/base/rpm/state
216     else
217         mkdir -m755 -p "$cfgdir"
218         local need_base=
219
220         if test -n "$have_apt"; then
221             findDir APTETCDIR    "$cfgdir"/aptetc      "$cfgdir"/base/apt/etc       /
222             findDir APTSTATEDIR  "$cfgdir"/aptstate    "$cfgdir"/base/apt/state     /
223             findDir APTCACHEDIR  "$cfgdir"/aptcache    "$cfgdir"/base/apt/cache     /
224             findDir APTARCHIVDIR "$cfgdir"/aptarchives "$cfgdir"/base/apt/archives  /
225             
226             test "$APTETCDIR"    != / || APTETCDIR=$cfgdir/base/apt/etc
227             test "$APTSTATEDIR"  != / || APTSTATEDIR=$cfgdir/base/apt/state
228             test "$APTCACHEDIR"  != / || APTCACHEDIR=$cfgdir/base/apt/cache
229             test "$APTARCHIVDIR" != / || APTARCHIVDIR=$cfgdir/base/apt/archive
230
231             test -d "$cfgdir"/aptetc   -a -d "$cfgdir"/aptstate -a \
232                  -d "$cfgdir"/aptcache -a -d "$cfgdir"/aptarchives || need_base=1
233         fi
234
235         findDir RPMETCDIR     "$cfgdir"/rpmetc   "$cfgdir"/base/rpm/etc    /
236         findDir RPMSTATEDIR   "$cfgdir"/rpmstate "$cfgdir"/base/rpm/state  /
237
238         test "$RPMETCDIR"   != / || RPMETCDIR=$cfgdir/base/rpm/etc
239         test "$RPMSTATEDIR" != / || RPMSTATEDIR=$cfgdir/base/rpm/state
240
241         test -d "$cfgdir"/rpmetc -a -d "$cfgdir"/rpmstate || need_base=1
242         test ! -e "$cfgdir"/base || need_base=
243
244         test -z "$need_base" || ln -s "$PKGCFGDIR" "$cfgdir"/base
245
246         mkdir -m755 -p "$PKGCFGDIR"
247         _createDirs "$APTETCDIR" "$APTSTATEDIR" "$APTCACHEDIR" "$APTARCHIVDIR" \
248                     "$RPMETCDIR" "$RPMSTATEDIR"
249     fi
250
251     ## Copy the files...
252     if test -n "$is_internalize"; then
253         if test -n "$have_apt"; then
254             _copySecure "$vdir" "$APTETCDIR" /etc/apt
255             pushd "$vdir" >/dev/null
256                 _hashAuto /etc/apt/apt.conf '/'
257             popd >/dev/null
258         fi
259
260         _copySecure "$vdir" "$RPMETCDIR"   /etc/rpm
261         _copySecure "$vdir" "$RPMSTATEDIR" /var/lib/rpm
262
263     else
264         if test -n "$have_apt"; then
265             _copySecureRev "$vdir" /etc/apt "$APTETCDIR"
266             _unhashAuto "$APTETCDIR"/apt.conf '/'
267         fi
268
269         _copySecureRev "$vdir" /etc/rpm     "$RPMETCDIR"
270         _copySecureRev "$vdir" /var/lib/rpm "$RPMSTATEDIR"
271     fi
272
273     ## Cleanups...
274     if test -n "$is_internalize"; then
275         :
276     else
277         tmpdir=$($_MKTEMPDIR /var/tmp/pgmgmt.XXXXXX)
278         trap "$_RM -rf $tmpdir" EXIT
279         pushd "$vdir" >/dev/null
280         $_EXEC_CD /var/lib $_MV rpm $tmpdir/
281         $_EXEC_CD /var/lib $_LN_S "$rpmdb_mntpoint" rpm
282         $_RM -rf $tmpdir
283     fi
284
285     ## Finish it...
286     if test -n "$is_internalize"; then
287         $_TOUCH "$cfgdir"/internal
288     else
289         $_RM -f "$cfgdir"/internal
290     fi
291 }
292
293 function processVserver_Debian()
294 {
295     local vserver=$1
296     local is_internalize=$2
297
298     if test -n "$is_internalize"; then
299         echo $"Debian vservers should be internalized everytime; do not know how to handle '$vserver'" >&2
300     else
301         echo $"External packagemanagement is not supported for Debian vserver" >&2
302     fi
303
304     return 1
305 }
306
307 function processVserver()
308 {
309     local vserver=$1
310     local is_external=
311     local skip=1
312     local vdir
313
314     ! $_VSERVER_INFO -q "$vserver" RUNNING || {
315         echo $"Can not operate on running vservers; please stop '$vserver' and retry again..."
316         return 1
317     } >&2
318
319     vdir=$($_VSERVER_INFO "$vserver" VDIR) && test -d "$vdir" || {
320         echo $"Vserver '$vserver' does not seem to exist; skipping it..."
321         return 1
322     } >&2
323     
324     pkgmgmt.isInternal "$vserver" || is_external=1
325
326     case "$is_external"X"$IS_INTERNALIZE"X"$IS_EXTERNALIZE" in
327         (*X1X1) echo $"Can not externalize and internalize at the same time";;
328         (*XX)   echo $"No operation specified; try '--help' for more information";;
329         (1XX1)  echo $"Vserver '$vserver' has already external packagemanagment; skipping it...";;
330         (X1X)   echo $"Vserver '$vserver' has already internal packagemanagment; skipping it...";;
331         (*)     skip=
332     esac >&2
333
334     test -z "$skip" || return 1
335
336     local style
337     _mountFilesystems  "$vserver"       || return 1
338     pkgmgmt.guessStyle "$vserver" style || return 1
339
340     case "$style" in
341         (redhat|mandrake)       processVserver_RH     "$vserver" "$IS_INTERNALIZE";;
342         (debian)                processVserver_Debian "$vserver" "$IS_INTERNALIZE";;
343         (*)
344             echo $"Vserver style '$style' is not supported for packagemanagment" >&2
345             return 1
346     esac
347
348     _umountFilesystems "$vserver"       || return 1
349 }
350
351 tmp=$(getopt -o y --long debug,externalize,internalize,help,version -n "$0" -- "$@") || exit 1
352 eval set -- "$tmp"
353
354 IS_EXTERNALIZE=
355 IS_INTERNALIZE=
356 IS_YES=
357
358 while true; do
359     case "$1" in
360         (--help)        showHelp $0;;
361         (--version)     showVersion;;
362         (--debug)       set -x;;
363         (--externalize) IS_EXTERNALIZE=1;;
364         (--internalize) IS_INTERNALIZE=1;;
365         (-y)            IS_YES=1;;
366         (--)            shift; break;;
367         (*)             echo $"vserver: internal error; arg=='$1'" >&2; exit 1;;
368     esac
369     shift
370 done
371
372 test -n "$1" || {
373     echo $"No vserver specified; try '--help' for more information"
374     exit 1
375 } >&2
376
377
378 set -e
379 init
380
381 ok=1
382 passed=
383 for i; do
384     processVserver "$i" && passed=1 || ok=
385 done
386     
387 test -z "$ok"     || exit 0
388 test -z "$passed" || exit 1
389 exit 2