Make sure /dev gets proper permissions.
[util-vserver.git] / scripts / vserver-build.functions
1 # $Id$  --*- sh -*--
2
3 # Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 #  
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; version 2 of the License.
8 #  
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #  
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 # Expected environment:
19 #     $VSERVER_NAME ... name of vserver
20
21 ROOTDIR=
22 ROOTDIR_REL=
23 CACHEDIR=
24 CACHEDIR_REL=
25 VSERVERDIRNAME=
26
27 VDIR=
28
29 _DEV_FILE=
30 _EXEC_DIR=
31
32 BUILD_INITPRE=
33 BUILD_INITPOST=
34
35 __BASE_GENERATED_FILES=()
36 __BASE_SUCCESS=
37
38 function makeDevEntry
39 {
40     local dst=$1/$2
41     case "$3" in
42         (c|b)   mknod -m$6 "$dst"  $3 $4 $5;;
43         (d)     mkdir -p -m$4 "$dst";;
44         (f)     touch "$dst"
45                 chmod $4 "$dst"
46                 ;;
47         (*)     echo "Unknown dev-entry mode '$3'" >&2
48                 false
49                 ;;
50     esac
51 }
52
53 function populateDev
54 {
55     local spec
56
57     mkdir -p -m755 "$VDIR"/dev
58     mkdir -m755 "$VDIR"/dev/pts
59
60     while read spec; do
61         makeDevEntry "$VDIR"/dev $spec
62     done <$_DEV_FILE
63 }
64
65 function populateDirectory
66 {
67     local dst=$1
68     local i
69     
70     shift
71     for i; do
72         local file=
73         
74         for file in "$i"/*; do
75             isRegularFile "$file" || continue
76             
77             cp -a "$file" "$dst/"
78         done
79     done
80 }
81
82 function _setRootDir
83 {
84     test -z "$ROOTDIR" || return 0
85     
86     for item in "\"$__CONFDIR/.defaults/vdirbase\" 1" "$__DEFAULT_VSERVERDIR"; do
87         eval set -- "$item"
88         ROOTDIR=$1
89         ROOTDIR_REL=$2
90         test ! -d "$ROOTDIR" || break
91     done
92
93     test -d "$ROOTDIR" || {
94         echo "Root-directory '$ROOTDIR' does not exist or is invalid" >&2
95         exit 1
96     }
97 }
98
99 function _setCacheDir
100 {
101     test -z "$CACHEDIR" || return 0
102     
103     for item in "\"$__CONFDIR/.defaults/cachebase\" 1" "$__PKGCACHEDIR"; do
104         eval set -- "$item"
105         CACHEDIR=$1
106         CACHEDIR_REL=$2
107         test ! -d "$CACHEDIR" || break
108     done
109
110     test -d "$CACHEDIR" || {
111         echo "Cache-directory '$CACHEDIR' does not exist or is invalid" >&2
112         exit 1
113     }
114 }
115
116 function _setVserverDirName
117 {
118     test -z "$VSERVERDIRNAME" || return 0
119     VSERVERDIRNAME="$VSERVER_NAME"
120 }
121
122 function _setVdir
123 {
124     VDIR="$ROOTDIR/$VSERVERDIRNAME"
125 }
126
127 function say
128 {
129     test -z "$OPTION_SILENT" || return 0
130     echo "$@"
131 }
132
133 function _renameVserverCfg
134 {
135     local suffix=.~$(date +'%s')~
136     local i
137     
138     for i in "$VDIR" "$SETUP_CONFDIR"; do
139         test ! -e "$i" || isDirectoryEmpty "$i" || {
140             mv "$i" "$i$suffix"
141             say "Renamed '$i' to '$i$suffix'"
142         }
143     done
144 }
145
146
147 ## Usage: getDistribution [<default>] [<ignore-config>]
148 function getDistribution
149 {
150     local ignore_config=$2
151     
152     if test -z "$DISTRIBUTION"; then
153         if test -e /etc/fedora-release; then
154             set -- $(cat /etc/fedora-release)
155             DISTRIBUTION=fdr$4
156         elif test -e /etc/redhat-release; then
157             set -- $(cat /etc/redhat-release)
158             DISTRIBUTION=rh$5
159         elif test -e /etc/debian_version; then
160             set -- $(cat /etc/debian_version)
161             DISTRIBUTION=deb$1
162         elif test -e /etc/SuSE-release; then
163             set -- $(cat /etc/SuSE-release)
164             DISTRIBUTION=suse$3
165         elif test -e /etc/gentoo-release; then
166             set -- $(cat /etc/gentoo-release)
167             DISTRIBUTION=gentoo$5
168         elif test -e /etc/slackware-version; then
169             set -- $(cat /etc/slackware-version)
170             DISTRIBUTION=slackware$2
171         elif test -n "$1"; then
172             DISTRIBUTION=$1
173         else
174             colpanic $"\
175 ERROR: Can not determine distribution; please specify it manually with
176   the '-d' option."
177         fi
178     fi
179
180     test -n "$ignore_config" -o \
181          -d "$__CONFDIR/.distributions/$DISTRIBUTION" -o \
182          -d "$__DISTRIBDIR/$DISTRIBUTION" ||
183             colpanic $"\
184 ERROR: Can not find configuration for the distribution '$DISTRIBUTION';
185   please read http://linux-vserver.org/HowToRegisterNewDistributions
186   for information how to add support for your own distribution."
187
188     export DISTRIBUTION
189 }
190
191 function base._addGeneratedFile
192 {
193     __BASE_GENERATED_FILES=( "${__BASE_GENERATED_FILES[@]}" "$@" )
194 }
195
196 ## Usage: initFilesystem [force]
197 function base.initFilesystem
198 {
199     test -z "$1" || _renameVserverCfg
200     { isDirectoryEmpty "$VDIR" && test  ! -e "$SETUP_CONFDIR"; } || colpanic $"\
201 vserver-topdirectory '$VDIR' and/or configuration at '$SETUP_CONFDIR'
202 exist already; please try to use '--force', or remove them manually."
203
204     mkdir -p -m755 "$VDIR"
205     $_SETATTR --~barrier "$VDIR"
206     base._addGeneratedFile "$VDIR"
207     
208     mkdir -p -m755 "$SETUP_CONFDIR"/apps "$VDIR"/etc
209     base._addGeneratedFile "$SETUP_CONFDIR"
210     
211     ln -s "$VDIR"                     "$SETUP_CONFDIR/vdir"
212     ln -s "$CACHEDIR/$VSERVERDIRNAME" "$SETUP_CONFDIR/cache"
213
214     populateDev
215
216     mkdir -p "$VDIR"/proc
217     findAndCopy "$VDIR"/etc/hosts         "$__CONFDIR"/.defaults/files/hosts "$__CONFDIR/.distributions/$DISTRIBUTION"/files/hosts \
218                                           "$__DISTRIBDIR/$DISTRIBUTION"/files/hosts "$__DISTRIBDIR"/defaults/files/hosts ""
219
220     for i in nsswitch.conf krb5.conf krb.conf krb.realms ldap.conf localtime resolv.conf; do
221         findAndCopy "$VDIR"/etc/$i  "$__CONFDIR/.defaults/files/$i" "$__CONFDIR/.distributions/$DISTRIBUTION/files/$i" ""
222     done
223 }
224
225 function base._initVariables
226 {
227     _setRootDir
228     _setCacheDir
229     _setVserverDirName
230     _setVdir
231
232     findFile _DEV_FILE      "$__CONFDIR/.distributions/$DISTRIBUTION/devs"      "$__DISTRIBDIR/$DISTRIBUTION/devs"     "$__DISTRIBDIR/defaults/devs"
233     findDir  _EXECDIR       "$__CONFDIR/.distributions/$DISTRIBUTION/execdir"   "$__DISTRIBDIR/$DISTRIBUTION/execdir"  /
234     findFile BUILD_INITPRE  "$__CONFDIR/.distributions/$DISTRIBUTION/initpre"   "$__DISTRIBDIR/$DISTRIBUTION/initpre"  ""
235     findFile BUILD_INITPOST "$__CONFDIR/.distributions/$DISTRIBUTION/initpost"  "$__DISTRIBDIR/$DISTRIBUTION/initpost" ""
236 }
237
238 function base.__cleanup
239 {
240     test -z "$OPTION_KEEP"    || return 0
241     test -z "$__BASE_SUCCESS" || return 0
242     
243     rm -rf "${__BASE_GENERATED_FILES[@]}"
244 }
245
246 function base.init
247 {
248     test -z "$SETUP_CONTEXT" || ! $_VSERVER_INFO -q "$SETUP_CONTEXT" RUNNING || \
249         panic $"\
250 Context '$SETUP_CONTEXT' is already in use. Please select another one."
251
252     trap "base.__cleanup" EXIT
253     base._initVariables
254 }
255
256 function base.setSuccess
257 {
258     __BASE_SUCCESS=1
259 }
260
261 function startSleepingGuest
262 {
263     local guest="$1"
264     local timeout="$2"
265     $_VSERVER "$guest" start --rescue --rescue-init bash -c "
266         exec  > /dev/null
267         exec 2> /dev/null
268         trap 'kill -s 9 -- -1; exit 0' INT
269         sleep $timeout
270         kill -s 15 -- -1
271         sleep 1
272         kill -s 9 -- -1"
273 }
274
275 function stopSleepingGuest
276 {
277     local guest="$1"
278     $_VKILL --xid "$guest" -s INT -- 1
279 }