give more comprehensive error-message
[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
28 function showHelp()
29 {
30     echo \
31 $"Usage: $0 --externalize|--internalize [-y] [--] <vserver-name>
32
33 Report bugs to <$PACKAGE_BUGREPORT>."
34     exit 0
35 }
36
37 function showVersion()
38 {
39     echo $"\
40 vpkg $PACKAGE_VERSION -- shows information about packages in vservers
41 This program is part of $PACKAGE_STRING
42
43 Copyright (C) 2004 Enrico Scholz
44 This program is free software; you may redistribute it under the terms of
45 the GNU General Public License.  This program has absolutely no warranty."
46     exit 0
47 }
48
49 function init()
50 {
51     if test -z "$WORKAROUND_106057"; then
52         rpmdb_mntpoint=/dev
53     else
54         rpmdb_mntpoint=/.rpmdb
55     fi
56     pkgmgmt.initVariables
57 }
58
59 function _createDirs()
60 {
61     for i; do
62         test "$i" || continue
63         mkdir -p -m755 "$i"
64     done
65 }
66
67 function _copySecure()
68 {
69     local chroot=$1
70     local srcdir=$2
71     local dstdir=$3
72
73     
74     ( cd "$srcdir" && tar chf - '.' ) | \
75     ( cd "$chroot" && $_EXEC_CD "$dstdir" $_TAR xf - )
76 }
77
78 function _copySecureRev()
79 {
80     local chroot=$1
81     local srcdir=$2
82     local dstdir=$3
83
84     ( cd "$chroot" && $_EXEC_CD "$srcdir" $_TAR cf - '.' ) | \
85     ( cd "$dstdir" && tar xf - )
86 }
87
88 function _hashAuto()
89 {
90     local hash=$2
91     local dir=$(dirname "$1")
92     local file=$(basename "$1")
93
94     $_EXEC_CD "$dir" "$(which test)" "$file" || return 0
95     
96     local tmp=$(mktemp /tmp/apt.conf.XXXXXX)
97     trap "rm -f $tmp" EXIT
98
99     $_EXEC_CD "$dir" /bin/cat "$file" | \
100         sed -e "s|^\([^$hash].*@autogenerated@\)|$hash$hash\1|" >$tmp
101
102     cat $tmp | $_EXEC_CD "$dir" "$(which cmp)" -s - "$file" || \
103         $_CHROOT_CAT "$1" <$tmp
104
105     rm -f $tmp
106 }
107
108 function _unhashAuto()
109 {
110     test -e "$1" || return 0
111
112     local hash=$2
113     local tmp=$(mktemp /tmp/apt.conf.XXXXXX)
114     trap "rm -f $tmp" EXIT
115
116     sed -e "s|^$hash$hash\(.*@autogenerated@\)|\1|" "$1" >$tmp
117     cmp -s "$tmp" "$1" || \
118         cat "$tmp" >"$1"
119
120     rm -f $tmp
121 }
122
123 function processVserver_RH()
124 {
125     local vserver=$1
126     local is_internalize=$2
127     local have_apt
128     local cfgdir
129     local i
130
131     cfgdir=$($_VSERVER_INFO "$vserver" APPDIR pkgmgmt) || \
132     cfgdir=$($_VSERVER_INFO "$vserver" APPDIR)/pkgmgmt
133
134     ## Figure out the environment....
135     have_apt=1
136     pkgmgmt.isAptAvailable "$cfgdir" "$vdir" "$is_internalize" || have_apt=
137
138     local APTETCDIR=
139     local APTSTATEDIR=
140     local APTCACHEDIR=
141     local APTARCHIVDIR=
142     local RPMETCDIR=
143     local RPMSTATEDIR=
144
145     ## Create directories and assign variables where configuration
146     ## can/will be found on the host
147     if test "$is_internalize"; then
148         pushd "$vdir" >/dev/null
149
150         test ! -L var/lib/rpm || {
151             $_EXEC_CD /var/lib /bin/rm            rpm &&
152             $_EXEC_CD /var/lib /bin/mkdir -m755   rpm &&
153             $_EXEC_CD /var/lib /bin/chown rpm:rpm rpm ||
154             :
155         } </dev/null 2>/dev/null
156
157         for i in var/cache/apt/{,archives/{,partial},genpkglist,gensrclist} \
158                  var/state/{,apt/{,lists/{,partial}}} \
159                  etc/apt etc/rpm; do
160             test -d "$i" ||
161                 $_EXEC_CD /$(dirname "$i") /bin/mkdir -m755 $(basename "$i") || :
162         done #2>/dev/null
163         
164         popd >/dev/null
165         
166         if test "$have_apt"; then
167             findDir APTETCDIR    "$cfgdir"/aptetc "$cfgdir"/base/apt/etc /etc/apt /
168         fi
169
170         findDir RPMETCDIR   "$cfgdir"/rpmetc   "$cfgdir"/base/rpm/etc    /etc/rpm /
171         findDir RPMSTATEDIR "$cfgdir"/rpmstate "$cfgdir"/base/rpm/state
172     else
173         mkdir -m755 -p "$cfgdir"
174         local need_base=
175
176         if test "$have_apt"; then
177             findDir APTETCDIR    "$cfgdir"/aptetc      "$cfgdir"/base/apt/etc       /
178             findDir APTSTATEDIR  "$cfgdir"/aptstate    "$cfgdir"/base/apt/state     /
179             findDir APTCACHEDIR  "$cfgdir"/aptcache    "$cfgdir"/base/apt/cache     /
180             findDir APTARCHIVDIR "$cfgdir"/aptarchives "$cfgdir"/base/apt/archives  /
181             
182             test "$APTETCDIR"    != / || APTETCDIR=$cfgdir/base/apt/etc
183             test "$APTSTATEDIR"  != / || APTSTATEDIR=$cfgdir/base/apt/state
184             test "$APTCACHEDIR"  != / || APTCACHEDIR=$cfgdir/base/apt/cache
185             test "$APTARCHIVDIR" != / || APTARCHIVDIR=$cfgdir/base/apt/archive
186
187             test -d "$cfgdir"/aptetc   -a -d "$cfgdir"/aptstate -a \
188                  -d "$cfgdir"/aptcache -a -d "$cfgdir"/aptarchives || need_base=1
189         fi
190
191         findDir RPMETCDIR     "$cfgdir"/rpmetc   "$cfgdir"/base/rpm/etc    /
192         findDir RPMSTATEDIR   "$cfgdir"/rpmstate "$cfgdir"/base/rpm/state  /
193
194         test "$RPMETCDIR"   != / || RPMETCDIR=$cfgdir/base/rpm/etc
195         test "$RPMSTATEDIR" != / || RPMSTATEDIR=$cfgdir/base/rpm/state
196
197         test -d "$cfgdir"/rpmetc -a -d "$cfgdir"/rpmstate || need_base=1
198         test ! -e "$cfgdir"/base || need_base=
199
200         test -z "$need_base" || ln -s "$PKGCFGDIR" "$cfgdir"/base
201
202         mkdir -m755 -p "$PKGCFGDIR"
203         _createDirs "$APTETCDIR" "$APTSTATEDIR" "$APTCACHEDIR" "$APTARCHIVDIR" \
204                     "$RPMETCDIR" "$RPMSTATEDIR"
205     fi
206
207     ## Copy the files...
208     if test "$is_internalize"; then
209         if test "$have_apt"; then
210             _copySecure "$vdir" "$APTETCDIR" /etc/apt
211             pushd "$vdir" >/dev/null
212                 _hashAuto /etc/apt/apt.conf '/'
213             popd >/dev/null
214         fi
215
216         _copySecure "$vdir" "$RPMETCDIR"   /etc/rpm
217         _copySecure "$vdir" "$RPMSTATEDIR" /var/lib/rpm
218
219     else
220         if test "$have_apt"; then
221             _copySecureRev "$vdir" /etc/apt "$APTETCDIR"
222             _unhashAuto "$APTETCDIR"/apt.conf '/'
223         fi
224
225         _copySecureRev "$vdir" /etc/rpm     "$RPMETCDIR"
226         _copySecureRev "$vdir" /var/lib/rpm "$RPMSTATEDIR"
227     fi
228
229     ## Cleanups...
230     if test "$is_internalize"; then
231         :
232     else
233         tmpdir=$(mktemp -d /var/tmp/pgmgmt.XXXXXX)
234         trap "rm -rf $tmpdir" EXIT
235         pushd "$vdir" >/dev/null
236         $_EXEC_CD /var/lib /bin/mv rpm $tmpdir/
237         $_EXEC_CD /var/lib /bin/ln -s "$rpmdb_mntpoint" rpm
238         rm -rf $tmpdir
239     fi
240
241     ## Finish it...
242     if test "$is_internalize"; then
243         touch "$cfgdir"/internal
244     else
245         rm -f "$cfgdir"/internal
246     fi
247 }
248
249 function processVserver_Debian()
250 {
251     local vserver=$1
252     local is_internalize=$2
253
254     if test "$is_internalize"; then
255         echo $"Debian vservers should be internalized everytime; do not know how to handle '$vserver'" >&2
256     else
257         echo $"External packagemanagement is not supported for Debian vserver" >&2
258     fi
259
260     return 1
261 }
262
263 function processVserver()
264 {
265     local vserver=$1
266     local is_external=
267     local skip=1
268     local vdir
269
270     ! $_VSERVER_INFO -q "$vserver" RUNNING || {
271         echo $"Can not operate on running vservers; please stop '$vserver' and retry again..."
272         return 1
273     } >&2
274
275     vdir=$($_VSERVER_INFO "$vserver" VDIR) && test -d "$vdir" || {
276         echo $"Vserver '$vserver' does not seem to exist; skipping it..."
277         return 1
278     } >&2
279     
280     pkgmgmt.isInternal "$vserver" || is_external=1
281
282     case "$is_external"X"$IS_INTERNALIZE"X"$IS_EXTERNALIZE" in
283         (*X1X1) echo $"Can not externalize and internalize at the same time";;
284         (*XX)   echo $"No operation specified; try '--help' for more information";;
285         (1XX1)  echo $"Vserver '$vserver' has already external packagemanagment; skipping it...";;
286         (X1X)   echo $"Vserver '$vserver' has already internal packagemanagment; skipping it...";;
287         (*)     skip=
288     esac >&2
289
290     test -z "$skip" || return 1
291
292     local style
293     pkgmgmt.guessStyle "$vserver" style || return 1
294
295     case "$style" in
296         (redhat|mandrake)       processVserver_RH     "$vserver" "$IS_INTERNALIZE";;
297         (debian)                processVserver_Debian "$vserver" "$IS_INTERNALIZE";;
298         (*)
299             echo $"Vserver style '$style' is not supported for packagemanagment" >&2
300             return 1
301     esac
302 }
303
304 tmp=$(getopt -o y --long debug,externalize,internalize,help,version -n "$0" -- "$@") || exit 1
305 eval set -- "$tmp"
306
307 IS_EXTERNALIZE=
308 IS_INTERNALIZE=
309 IS_YES=
310
311 while true; do
312     case "$1" in
313         (--help)        showHelp $0;;
314         (--version)     showVersion;;
315         (--debug)       set -x;;
316         (--externalize) IS_EXTERNALIZE=1;;
317         (--internalize) IS_INTERNALIZE=1;;
318         (-y)            IS_YES=1;;
319         (--)            shift; break;;
320         (*)             echo $"vserver: internal error; arg=='$1'" >&2; exit 1;;
321     esac
322     shift
323 done
324
325 test "$1" || {
326     echo $"No vserver specified; try '--help' for more information"
327     exit 1
328 } >&2
329
330
331 set -e
332 init
333
334 ok=1
335 passed=
336 for i; do
337     processVserver "$i" && passed=1 || ok=
338 done
339     
340 test -z "$ok"     || exit 0
341 test -z "$passed" || exit 1
342 exit 2