Add the /dev/fd symlink that is expected by more and more things.
[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         (l)     ln -s "$4" "$dst"
48                 test -z "$5" || chmod "$5" "$dst"
49                 ;;
50         (*)     echo "Unknown dev-entry mode '$3'" >&2
51                 false
52                 ;;
53     esac
54 }
55
56 function populateDev
57 {
58     local spec
59
60     mkdir -p -m755 "$VDIR"/dev
61     mkdir -m755 "$VDIR"/dev/pts
62
63     while read spec; do
64         makeDevEntry "$VDIR"/dev $spec
65     done <$_DEV_FILE
66 }
67
68 function populateDirectory
69 {
70     local dst=$1
71     local i
72     
73     shift
74     for i; do
75         local file=
76         
77         for file in "$i"/*; do
78             isRegularFile "$file" || continue
79             
80             cp -a "$file" "$dst/"
81         done
82     done
83 }
84
85 function _setRootDir
86 {
87     test -z "$ROOTDIR" || return 0
88     
89     for item in "\"$__CONFDIR/.defaults/vdirbase\" 1" "$__DEFAULT_VSERVERDIR"; do
90         eval set -- "$item"
91         ROOTDIR=$1
92         ROOTDIR_REL=$2
93         test ! -d "$ROOTDIR" || break
94     done
95
96     test -d "$ROOTDIR" || {
97         echo "Root-directory '$ROOTDIR' does not exist or is invalid" >&2
98         exit 1
99     }
100 }
101
102 function _setCacheDir
103 {
104     test -z "$CACHEDIR" || return 0
105     
106     for item in "\"$__CONFDIR/.defaults/cachebase\" 1" "$__PKGCACHEDIR"; do
107         eval set -- "$item"
108         CACHEDIR=$1
109         CACHEDIR_REL=$2
110         test ! -d "$CACHEDIR" || break
111     done
112
113     test -d "$CACHEDIR" || {
114         echo "Cache-directory '$CACHEDIR' does not exist or is invalid" >&2
115         exit 1
116     }
117 }
118
119 function _setVserverDirName
120 {
121     test -z "$VSERVERDIRNAME" || return 0
122     VSERVERDIRNAME="$VSERVER_NAME"
123 }
124
125 function _setVdir
126 {
127     VDIR="$ROOTDIR/$VSERVERDIRNAME"
128 }
129
130 function say
131 {
132     test -z "$OPTION_SILENT" || return 0
133     echo "$@"
134 }
135
136 function _renameVserverCfg
137 {
138     local suffix=.~$(date +'%s')~
139     local i
140     
141     for i in "$VDIR" "$SETUP_CONFDIR"; do
142         test ! -e "$i" || isDirectoryEmpty "$i" || {
143             mv "$i" "$i$suffix"
144             say "Renamed '$i' to '$i$suffix'"
145         }
146     done
147 }
148
149
150 ## Usage: getDistribution [<default>] [<ignore-config>]
151 function getDistribution
152 {
153     local ignore_config=$2
154     
155     if test -z "$DISTRIBUTION"; then
156         if test -e /etc/fedora-release; then
157             set -- $(cat /etc/fedora-release)
158             DISTRIBUTION=fdr$4
159         elif test -e /etc/redhat-release; then
160             set -- $(cat /etc/redhat-release)
161             DISTRIBUTION=rh$5
162         elif test -e /etc/debian_version; then
163             set -- $(cat /etc/debian_version)
164             DISTRIBUTION=deb$1
165         elif test -e /etc/SuSE-release; then
166             set -- $(cat /etc/SuSE-release)
167             DISTRIBUTION=suse$3
168         elif test -e /etc/gentoo-release; then
169             set -- $(cat /etc/gentoo-release)
170             DISTRIBUTION=gentoo$5
171         elif test -e /etc/slackware-version; then
172             set -- $(cat /etc/slackware-version)
173             DISTRIBUTION=slackware$2
174         elif test -n "$1"; then
175             DISTRIBUTION=$1
176         else
177             colpanic $"\
178 ERROR: Can not determine distribution; please specify it manually with
179   the '-d' option."
180         fi
181     fi
182
183     test -n "$ignore_config" -o \
184          -d "$__CONFDIR/.distributions/$DISTRIBUTION" -o \
185          -d "$__DISTRIBDIR/$DISTRIBUTION" ||
186             colpanic $"\
187 ERROR: Can not find configuration for the distribution '$DISTRIBUTION';
188   please read http://linux-vserver.org/HowToRegisterNewDistributions
189   for information how to add support for your own distribution."
190
191     export DISTRIBUTION
192 }
193
194 function base._addGeneratedFile
195 {
196     __BASE_GENERATED_FILES=( "${__BASE_GENERATED_FILES[@]}" "$@" )
197 }
198
199 ## Usage: initFilesystem [force]
200 function base.initFilesystem
201 {
202     test -z "$1" || _renameVserverCfg
203     { isDirectoryEmpty "$VDIR" && test  ! -e "$SETUP_CONFDIR"; } || colpanic $"\
204 vserver-topdirectory '$VDIR' and/or configuration at '$SETUP_CONFDIR'
205 exist already; please try to use '--force', or remove them manually."
206
207     mkdir -p -m755 "$VDIR"
208     $_SETATTR --~barrier "$VDIR"
209     $_SETATTR --barrier "$VDIR"/.. || colwarn $"\
210 WARNING: could not set the barrier attribute on '$VDIR/..',
211          please set it manually."
212     base._addGeneratedFile "$VDIR"
213     
214     mkdir -p -m755 "$SETUP_CONFDIR"/apps "$VDIR"/etc
215     base._addGeneratedFile "$SETUP_CONFDIR"
216     
217     ln -s "$VDIR"                     "$SETUP_CONFDIR/vdir"
218     ln -s "$CACHEDIR/$VSERVERDIRNAME" "$SETUP_CONFDIR/cache"
219
220     populateDev
221
222     mkdir -p "$VDIR"/proc
223     findAndCopy "$VDIR"/etc/hosts         "$__CONFDIR"/.defaults/files/hosts "$__CONFDIR/.distributions/$DISTRIBUTION"/files/hosts \
224                                           "$__DISTRIBDIR/$DISTRIBUTION"/files/hosts "$__DISTRIBDIR"/defaults/files/hosts ""
225
226     for i in nsswitch.conf krb5.conf krb.conf krb.realms ldap.conf localtime resolv.conf; do
227         findAndCopy "$VDIR"/etc/$i  "$__CONFDIR/.defaults/files/$i" "$__CONFDIR/.distributions/$DISTRIBUTION/files/$i" ""
228     done
229 }
230
231 function base._initVariables
232 {
233     _setRootDir
234     _setCacheDir
235     _setVserverDirName
236     _setVdir
237
238     findFile _DEV_FILE      "$__CONFDIR/.distributions/$DISTRIBUTION/devs"      "$__DISTRIBDIR/$DISTRIBUTION/devs"     "$__DISTRIBDIR/defaults/devs"
239     findDir  _EXECDIR       "$__CONFDIR/.distributions/$DISTRIBUTION/execdir"   "$__DISTRIBDIR/$DISTRIBUTION/execdir"  /
240     findFile BUILD_INITPRE  "$__CONFDIR/.distributions/$DISTRIBUTION/initpre"   "$__DISTRIBDIR/$DISTRIBUTION/initpre"  ""
241     findFile BUILD_INITPOST "$__CONFDIR/.distributions/$DISTRIBUTION/initpost"  "$__DISTRIBDIR/$DISTRIBUTION/initpost" ""
242 }
243
244 function base.__cleanup
245 {
246     test -z "$OPTION_KEEP"    || return 0
247     test -z "$__BASE_SUCCESS" || return 0
248     
249     rm -rf "${__BASE_GENERATED_FILES[@]}"
250 }
251
252 function base.init
253 {
254     test -z "$SETUP_CONTEXT" || ! $_VSERVER_INFO -q "$SETUP_CONTEXT" RUNNING || \
255         panic $"\
256 Context '$SETUP_CONTEXT' is already in use. Please select another one."
257
258     trap "base.__cleanup" EXIT
259     base._initVariables
260 }
261
262 function base.setSuccess
263 {
264     __BASE_SUCCESS=1
265 }
266
267 function startSleepingGuest
268 {
269     local guest="$1"
270     local timeout="${2:-15}"
271     $_VSERVER "$guest" start --rescue --rescue-init bash -c "
272         exec  > /dev/null
273         exec 2> /dev/null
274         trap 'kill -s 9 -- -1; exit 0' INT
275         i=0
276         while [ \$i -lt $timeout ]; do
277             sleep 1
278             let ++i
279         done
280         kill -s 15 -- -1
281         sleep 1
282         kill -s 9 -- -1"
283 }
284
285 function stopSleepingGuest
286 {
287     local guest="$1"
288     $_VSERVER "$guest" stop --rescue-init
289 }