]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-functions
Merge pull request #2790 from ronnychevalier/rc/systemctl_missing_oom_check
[thirdparty/systemd.git] / test / test-functions
CommitLineData
898720b7
HH
1#!/bin/bash
2# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3# ex: ts=8 sw=4 sts=4 et filetype=sh
4PATH=/sbin:/bin:/usr/sbin:/usr/bin
5export PATH
6
0fe15dc8 7LOOKS_LIKE_DEBIAN=$(source /etc/os-release && [[ "$ID" = "debian" || "$ID_LIKE" = "debian" ]] && echo yes)
0d6e798a
HH
8KERNEL_VER=${KERNEL_VER-$(uname -r)}
9KERNEL_MODS="/lib/modules/$KERNEL_VER/"
898720b7 10
3486cb6c
MP
11if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then
12 echo "WARNING! Cannot determine rootlibdir from pkg-config, assuming /usr/lib/systemd" >&2
13 ROOTLIBDIR=/usr/lib/systemd
14fi
15
09f6f45a
EV
16BASICTOOLS="sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm"
17DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find"
889a9042 18
c6a77179
RC
19function find_qemu_bin() {
20 # SUSE and Red Hat call the binary qemu-kvm
21 # Debian and Gentoo call it kvm
22 [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a kvm qemu-kvm 2>/dev/null | grep '^/' -m1)
23
24 [ "$ARCH" ] || ARCH=$(uname -m)
25 case $ARCH in
26 x86_64)
27 # QEMU's own build system calls it qemu-system-x86_64
28 [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-x86_64 2>/dev/null | grep '^/' -m1)
29 ;;
30 i*86)
31 # new i386 version of QEMU
32 [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-i386 2>/dev/null | grep '^/' -m1)
33
34 # i386 version of QEMU
35 [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu 2>/dev/null | grep '^/' -m1)
36 ;;
37 esac
38
39 if [ ! -e "$QEMU_BIN" ]; then
40 echo "Could not find a suitable QEMU binary" >&2
41 return 1
42 fi
43}
44
889a9042 45run_qemu() {
b6f0c419
HH
46 if [ -f /etc/machine-id ]; then
47 read MACHINE_ID < /etc/machine-id
48 [ -z "$INITRD" ] && [ -e "/boot/$MACHINE_ID/$KERNEL_VER/initrd" ] \
49 && INITRD="/boot/$MACHINE_ID/$KERNEL_VER/initrd"
50 [ -z "$KERNEL_BIN" ] && [ -e "/boot/$MACHINE_ID/$KERNEL_VER/linux" ] \
51 && KERNEL_BIN="/boot/$MACHINE_ID/$KERNEL_VER/linux"
52 fi
53
61fea35e
EV
54 default_fedora_initrd=/boot/initramfs-${KERNEL_VER}.img
55 default_debian_initrd=/boot/initrd.img-${KERNEL_VER}
c6a77179 56 [ "$KERNEL_BIN" ] || KERNEL_BIN=/boot/vmlinuz-$KERNEL_VER
61fea35e
EV
57 [ "$INITRD" ] || { [ -e "$default_fedora_initrd" ] && INITRD=$default_fedora_initrd; }
58 [ "$INITRD" ] || { [ "$LOOKS_LIKE_DEBIAN" ] && [ -e "$default_debian_initrd" ] && INITRD=$default_debian_initrd; }
c6a77179
RC
59 [ "$QEMU_SMP" ] || QEMU_SMP=1
60
61 find_qemu_bin || return 1
62
63 KERNEL_APPEND="root=/dev/sda1 \
64systemd.log_level=debug \
65raid=noautodetect \
66loglevel=2 \
3486cb6c 67init=$ROOTLIBDIR/systemd \
c6a77179
RC
68ro \
69console=ttyS0 \
70selinux=0 \
71$KERNEL_APPEND \
72"
73
dbf43a42 74 QEMU_OPTIONS="-smp $QEMU_SMP \
c6a77179
RC
75-net none \
76-m 512M \
77-nographic \
78-kernel $KERNEL_BIN \
79"
80
81 if [ "$INITRD" ]; then
82 QEMU_OPTIONS="$QEMU_OPTIONS -initrd $INITRD"
83 fi
84
dbf43a42
DM
85 if [ -c /dev/kvm ]; then
86 QEMU_OPTIONS="$QEMU_OPTIONS -machine accel=kvm -enable-kvm -cpu host"
87 fi
88
8a8332f7
ZJS
89 ( set -x
90 $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND" $TESTDIR/rootdisk.img ) || return 1
889a9042
RC
91}
92
93run_nspawn() {
8a8332f7 94 set -x
24be78d7 95 ../../systemd-nspawn --register=no --directory=$TESTDIR/nspawn-root $ROOTLIBDIR/systemd $KERNEL_APPEND
889a9042
RC
96}
97
98setup_basic_environment() {
99 # create the basic filesystem layout
100 setup_basic_dirs
101
102 install_systemd
103 install_missing_libraries
104 install_config_files
105 create_rc_local
106 install_basic_tools
107 install_libnss
108 install_pam
109 install_dbus
110 install_fonts
111 install_keymaps
112 install_terminfo
113 install_execs
9974ff63 114 install_fsck
889a9042
RC
115 install_plymouth
116 install_debug_tools
117 install_ld_so_conf
e3ce42e7 118 setup_selinux
889a9042
RC
119 strip_binaries
120 install_depmod_files
121 generate_module_dependencies
889a9042
RC
122}
123
e3ce42e7
EV
124setup_selinux() {
125 # don't forget KERNEL_APPEND='... selinux=1 ...'
126 if [[ "$SETUP_SELINUX" != "yes" ]]; then
127 ddebug "Don't setup SELinux"
128 return 0
129 fi
130 ddebug "Setup SELinux"
131 local _conf_dir=/etc/selinux
132 local _fixfiles_tools="bash uname cat sort uniq awk grep egrep head expr find rm secon setfiles"
133
134 rm -rf $initdir/$_conf_dir
135 if ! cp -ar $_conf_dir $initdir/$_conf_dir; then
136 dfatal "Failed to copy $_conf_dir"
137 exit 1
138 fi
139
140 cat <<EOF >$initdir/etc/systemd/system/autorelabel.service
141[Unit]
142Description=Relabel all filesystems
143DefaultDependencies=no
144Requires=local-fs.target
145Conflicts=shutdown.target
146After=local-fs.target
147Before=sysinit.target shutdown.target
148ConditionSecurity=selinux
149ConditionPathExists=|/.autorelabel
150
151[Service]
152ExecStart=/bin/sh -x -c 'echo 0 >/sys/fs/selinux/enforce && fixfiles -f -F relabel && rm /.autorelabel && systemctl --force reboot'
153Type=oneshot
154TimeoutSec=0
155RemainAfterExit=yes
156EOF
157
158 touch $initdir/.autorelabel
159 mkdir -p $initdir/etc/systemd/system/basic.target.wants
160 ln -fs autorelabel.service $initdir/etc/systemd/system/basic.target.wants/autorelabel.service
161
162 dracut_install $_fixfiles_tools
163 dracut_install fixfiles
164 dracut_install sestatus
165}
166
a2fbff31
EV
167install_valgrind() {
168 if ! type -p valgrind; then
169 dfatal "Failed to install valgrind"
170 exit 1
171 fi
172
173 local _valgrind_bins=$(strace -e execve valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if /^execve\("([^"]+)"/')
174 dracut_install $_valgrind_bins
175
176 local _valgrind_libs=$(LD_DEBUG=files valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if m{calling init: (/.*vgpreload_.*)}')
177 dracut_install $_valgrind_libs
178
179 local _valgrind_dbg_and_supp=$(
180 strace -e open valgrind /bin/true 2>&1 >/dev/null |
181 perl -lne 'if (my ($fname) = /^open\("([^"]+).*= (?!-)\d+/) { print $fname if $fname =~ /debug|\.supp$/ }'
182 )
183 dracut_install $_valgrind_dbg_and_supp
184}
185
cb2f9d3f
EV
186create_valgrind_wrapper() {
187 local _valgrind_wrapper=$initdir/$ROOTLIBDIR/systemd-under-valgrind
188 ddebug "Create $_valgrind_wrapper"
189 cat >$_valgrind_wrapper <<EOF
190#!/bin/bash
191
192exec valgrind --leak-check=full --log-file=/valgrind.out $ROOTLIBDIR/systemd "\$@"
193EOF
194 chmod 0755 $_valgrind_wrapper
195}
196
9974ff63
EV
197install_fsck() {
198 dracut_install /sbin/fsck*
199 dracut_install -o /bin/fsck*
200}
201
889a9042
RC
202install_dmevent() {
203 instmods dm_crypt =crypto
204 type -P dmeventd >/dev/null && dracut_install dmeventd
205 inst_libdir_file "libdevmapper-event.so*"
ac289ce3
EV
206 if [[ "$LOOKS_LIKE_DEBIAN" ]]; then
207 # dmsetup installs 55-dm and 60-persistent-storage-dm on Debian/Ubuntu
208 # see https://anonscm.debian.org/cgit/pkg-lvm/lvm2.git/tree/debian/patches/0007-udev.patch
209 inst_rules 55-dm.rules 60-persistent-storage-dm.rules
210 else
211 inst_rules 10-dm.rules 13-dm-disk.rules 95-dm-notify.rules
212 fi
889a9042
RC
213}
214
215install_systemd() {
216 # install compiled files
8a8332f7 217 (cd $TEST_BASE_DIR/..; set -x; make DESTDIR=$initdir install)
889a9042 218 # remove unneeded documentation
23756070 219 rm -fr $initdir/usr/share/{man,doc}
889a9042
RC
220 # we strip binaries since debug symbols increase binaries size a lot
221 # and it could fill the available space
222 strip_binaries
223}
224
225install_missing_libraries() {
226 # install possible missing libraries
227 for i in $initdir/{sbin,bin}/* $initdir/lib/systemd/*; do
228 inst_libs $i
229 done
230}
231
232create_empty_image() {
739d81dd 233 rm -f "$TESTDIR/rootdisk.img"
889a9042 234 # Create the blank file to use as a root filesystem
1b1eae69 235 dd if=/dev/null of="$TESTDIR/rootdisk.img" bs=1M seek=400
889a9042 236 LOOPDEV=$(losetup --show -P -f $TESTDIR/rootdisk.img)
739d81dd 237 [ -b "$LOOPDEV" ] || return 1
889a9042 238 echo "LOOPDEV=$LOOPDEV" >> $STATEFILE
edbced8a 239 sfdisk "$LOOPDEV" <<EOF
1b1eae69 240,390M
889a9042
RC
241,
242EOF
243
739d81dd 244 mkfs.ext3 -L systemd "${LOOPDEV}p1"
889a9042
RC
245}
246
247check_result_nspawn() {
248 ret=1
249 [[ -e $TESTDIR/nspawn-root/testok ]] && ret=0
250 [[ -f $TESTDIR/nspawn-root/failed ]] && cp -a $TESTDIR/nspawn-root/failed $TESTDIR
251 cp -a $TESTDIR/nspawn-root/var/log/journal $TESTDIR
252 [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
253 ls -l $TESTDIR/journal/*/*.journal
254 test -s $TESTDIR/failed && ret=$(($ret+1))
255 return $ret
256}
257
258strip_binaries() {
5a613464
EV
259 if [[ "$STRIP_BINARIES" = "no" ]]; then
260 ddebug "Don't strip binaries"
261 return 0
262 fi
889a9042
RC
263 ddebug "Strip binaries"
264 find "$initdir" -executable -not -path '*/lib/modules/*.ko' -type f | xargs strip --strip-unneeded | ddebug
265}
266
267create_rc_local() {
268 mkdir -p $initdir/etc/rc.d
269 cat >$initdir/etc/rc.d/rc.local <<EOF
270#!/bin/bash
271exit 0
272EOF
273 chmod 0755 $initdir/etc/rc.d/rc.local
274}
275
276install_execs() {
c7eda013
EV
277 ddebug "install any Execs from the service files"
278 (
279 export PKG_CONFIG_PATH=$TEST_BASE_DIR/../src/core/
280 systemdsystemunitdir=$(pkg-config --variable=systemdsystemunitdir systemd)
281 systemduserunitdir=$(pkg-config --variable=systemduserunitdir systemd)
282 egrep -ho '^Exec[^ ]*=[^ ]+' $initdir/{$systemdsystemunitdir,$systemduserunitdir}/*.service \
283 | while read i; do
284 i=${i##Exec*=}; i=${i##-}
285 inst $i
286 done
287 )
889a9042
RC
288}
289
290generate_module_dependencies() {
291 if [[ -d $initdir/lib/modules/$KERNEL_VER ]] && \
292 ! depmod -a -b "$initdir" $KERNEL_VER; then
293 dfatal "\"depmod -a $KERNEL_VER\" failed."
294 exit 1
295 fi
296}
297
298install_depmod_files() {
299 inst /lib/modules/$KERNEL_VER/modules.order
300 inst /lib/modules/$KERNEL_VER/modules.builtin
301}
302
303install_plymouth() {
304 # install plymouth, if found... else remove plymouth service files
305 # if [ -x /usr/libexec/plymouth/plymouth-populate-initrd ]; then
306 # PLYMOUTH_POPULATE_SOURCE_FUNCTIONS="$TEST_BASE_DIR/test-functions" \
307 # /usr/libexec/plymouth/plymouth-populate-initrd -t $initdir
308 # dracut_install plymouth plymouthd
309 # else
310 rm -f $initdir/{usr/lib,etc}/systemd/system/plymouth* $initdir/{usr/lib,etc}/systemd/system/*/plymouth*
311 # fi
312}
313
314install_ld_so_conf() {
315 cp -a /etc/ld.so.conf* $initdir/etc
316 ldconfig -r "$initdir"
317}
318
319install_config_files() {
320 inst /etc/sysconfig/init
321 inst /etc/passwd
322 inst /etc/shadow
bf3a947c 323 inst /etc/login.defs
889a9042
RC
324 inst /etc/group
325 inst /etc/shells
326 inst /etc/nsswitch.conf
327 inst /etc/pam.conf
328 inst /etc/securetty
329 inst /etc/os-release
330 inst /etc/localtime
331 # we want an empty environment
332 > $initdir/etc/environment
333 > $initdir/etc/machine-id
334 # set the hostname
335 echo systemd-testsuite > $initdir/etc/hostname
336 # fstab
337 cat >$initdir/etc/fstab <<EOF
338LABEL=systemd / ext3 rw 0 1
339EOF
340}
341
342install_basic_tools() {
343 [[ $BASICTOOLS ]] && dracut_install $BASICTOOLS
4be4833e 344 dracut_install -o sushell
7d023341
MP
345 # in Debian ldconfig is just a shell script wrapper around ldconfig.real
346 dracut_install -o ldconfig.real
889a9042
RC
347}
348
349install_debug_tools() {
350 [[ $DEBUGTOOLS ]] && dracut_install $DEBUGTOOLS
351}
352
353install_libnss() {
354 # install libnss_files for login
cffae62b 355 NSS_LIBS=$(LD_DEBUG=files getent passwd 2>&1 >/dev/null |sed -n '/calling init: .*libnss_/ {s!^.* /!/!; p}')
99877b7e 356 dracut_install $NSS_LIBS
889a9042
RC
357}
358
359install_dbus() {
3486cb6c
MP
360 inst $ROOTLIBDIR/system/dbus.socket
361 inst $ROOTLIBDIR/system/dbus.service
889a9042
RC
362
363 find \
e63b61be 364 /etc/dbus-1 /usr/share/dbus-1 -xtype f \
889a9042
RC
365 | while read file; do
366 inst $file
367 done
368}
369
370install_pam() {
0fe15dc8
EV
371 (
372 [[ "$LOOKS_LIKE_DEBIAN" ]] && type -p dpkg-architecture &>/dev/null && find "/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security" -xtype f
889a9042
RC
373 find \
374 /etc/pam.d \
375 /etc/security \
376 /lib64/security \
377 /lib/security -xtype f \
0fe15dc8 378 ) | while read file; do
889a9042
RC
379 inst $file
380 done
417491f1 381
d5172c79
EV
382 # pam_unix depends on unix_chkpwd.
383 # see http://www.linux-pam.org/Linux-PAM-html/sag-pam_unix.html
384 dracut_install -o unix_chkpwd
385
417491f1
EV
386 [[ "$LOOKS_LIKE_DEBIAN" ]] &&
387 cp /etc/pam.d/systemd-user $initdir/etc/pam.d/
889a9042
RC
388}
389
390install_keymaps() {
391 for i in \
392 /usr/lib/kbd/keymaps/include/* \
393 /usr/lib/kbd/keymaps/i386/include/* \
394 /usr/lib/kbd/keymaps/i386/qwerty/us.*; do
395 [[ -f $i ]] || continue
396 inst $i
397 done
398}
399
400install_fonts() {
401 for i in \
25b47f96 402 /usr/lib/kbd/consolefonts/eurlatgr* \
889a9042
RC
403 /usr/lib/kbd/consolefonts/latarcyrheb-sun16*; do
404 [[ -f $i ]] || continue
405 inst $i
406 done
407}
408
409install_terminfo() {
410 for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do
411 [ -f ${_terminfodir}/l/linux ] && break
412 done
413 dracut_install -o ${_terminfodir}/l/linux
414}
415
416setup_testsuite() {
53d90f95 417 cp $TEST_BASE_DIR/testsuite.target $initdir/etc/systemd/system/
5c404f1a 418 cp $TEST_BASE_DIR/end.service $initdir/etc/systemd/system/
889a9042
RC
419
420 mkdir -p $initdir/etc/systemd/system/testsuite.target.wants
421 ln -fs $TEST_BASE_DIR/testsuite.service $initdir/etc/systemd/system/testsuite.target.wants/testsuite.service
422 ln -fs $TEST_BASE_DIR/end.service $initdir/etc/systemd/system/testsuite.target.wants/end.service
423
424 # make the testsuite the default target
425 ln -fs testsuite.target $initdir/etc/systemd/system/default.target
426}
427
428setup_nspawn_root() {
429 rm -fr $TESTDIR/nspawn-root
430 ddebug "cp -ar $initdir $TESTDIR/nspawn-root"
431 cp -ar $initdir $TESTDIR/nspawn-root
432 # we don't mount in the nspawn root
433 rm -f $TESTDIR/nspawn-root/etc/fstab
434}
435
0d6e798a 436setup_basic_dirs() {
889a9042
RC
437 mkdir -p $initdir/run
438 mkdir -p $initdir/etc/systemd/system
439 mkdir -p $initdir/var/log/journal
440
0d6e798a 441 for d in usr/bin usr/sbin bin etc lib "$libdir" sbin tmp usr var var/log dev proc sys sysroot root run run/lock run/initramfs; do
898720b7
HH
442 if [ -L "/$d" ]; then
443 inst_symlink "/$d"
444 else
0d6e798a 445 inst_dir "/$d"
898720b7
HH
446 fi
447 done
448
449 ln -sfn /run "$initdir/var/run"
450 ln -sfn /run/lock "$initdir/var/lock"
451}
452
453inst_libs() {
454 local _bin=$1
455 local _so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
456 local _file _line
457
458 LC_ALL=C ldd "$_bin" 2>/dev/null | while read _line; do
459 [[ $_line = 'not a dynamic executable' ]] && break
460
461 if [[ $_line =~ $_so_regex ]]; then
462 _file=${BASH_REMATCH[1]}
463 [[ -e ${initdir}/$_file ]] && continue
464 inst_library "$_file"
465 continue
466 fi
467
468 if [[ $_line =~ not\ found ]]; then
469 dfatal "Missing a shared library required by $_bin."
470 dfatal "Run \"ldd $_bin\" to find out what it is."
471 dfatal "$_line"
472 dfatal "dracut cannot create an initrd."
473 exit 1
474 fi
475 done
476}
477
478import_testdir() {
479 STATEFILE=".testdir"
480 [[ -e $STATEFILE ]] && . $STATEFILE
481 if [[ -z "$TESTDIR" ]] || [[ ! -d "$TESTDIR" ]]; then
482 TESTDIR=$(mktemp --tmpdir=/var/tmp -d -t systemd-test.XXXXXX)
483 echo "TESTDIR=\"$TESTDIR\"" > $STATEFILE
484 export TESTDIR
485 fi
486}
487
889a9042
RC
488import_initdir() {
489 initdir=$TESTDIR/root
490 export initdir
491}
492
898720b7
HH
493## @brief Converts numeric logging level to the first letter of level name.
494#
495# @param lvl Numeric logging level in range from 1 to 6.
496# @retval 1 if @a lvl is out of range.
497# @retval 0 if @a lvl is correct.
498# @result Echoes first letter of level name.
499_lvl2char() {
500 case "$1" in
501 1) echo F;;
502 2) echo E;;
503 3) echo W;;
504 4) echo I;;
505 5) echo D;;
506 6) echo T;;
507 *) return 1;;
508 esac
509}
510
511## @brief Internal helper function for _do_dlog()
512#
513# @param lvl Numeric logging level.
514# @param msg Message.
515# @retval 0 It's always returned, even if logging failed.
516#
517# @note This function is not supposed to be called manually. Please use
518# dtrace(), ddebug(), or others instead which wrap this one.
519#
520# This function calls _do_dlog() either with parameter msg, or if
521# none is given, it will read standard input and will use every line as
522# a message.
523#
524# This enables:
525# dwarn "This is a warning"
526# echo "This is a warning" | dwarn
527LOG_LEVEL=4
528
529dlog() {
530 [ -z "$LOG_LEVEL" ] && return 0
531 [ $1 -le $LOG_LEVEL ] || return 0
532 local lvl="$1"; shift
533 local lvlc=$(_lvl2char "$lvl") || return 0
534
535 if [ $# -ge 1 ]; then
536 echo "$lvlc: $*"
537 else
538 while read line; do
539 echo "$lvlc: " "$line"
540 done
541 fi
542}
543
544## @brief Logs message at TRACE level (6)
545#
546# @param msg Message.
547# @retval 0 It's always returned, even if logging failed.
548dtrace() {
549 set +x
550 dlog 6 "$@"
551 [ -n "$debug" ] && set -x || :
552}
553
554## @brief Logs message at DEBUG level (5)
555#
556# @param msg Message.
557# @retval 0 It's always returned, even if logging failed.
558ddebug() {
0d6e798a 559# set +x
898720b7 560 dlog 5 "$@"
0d6e798a 561# [ -n "$debug" ] && set -x || :
898720b7
HH
562}
563
564## @brief Logs message at INFO level (4)
565#
566# @param msg Message.
567# @retval 0 It's always returned, even if logging failed.
568dinfo() {
569 set +x
570 dlog 4 "$@"
571 [ -n "$debug" ] && set -x || :
572}
573
574## @brief Logs message at WARN level (3)
575#
576# @param msg Message.
577# @retval 0 It's always returned, even if logging failed.
578dwarn() {
579 set +x
580 dlog 3 "$@"
581 [ -n "$debug" ] && set -x || :
582}
583
584## @brief Logs message at ERROR level (2)
585#
586# @param msg Message.
587# @retval 0 It's always returned, even if logging failed.
588derror() {
0d6e798a 589# set +x
898720b7 590 dlog 2 "$@"
0d6e798a 591# [ -n "$debug" ] && set -x || :
898720b7
HH
592}
593
594## @brief Logs message at FATAL level (1)
595#
596# @param msg Message.
597# @retval 0 It's always returned, even if logging failed.
598dfatal() {
599 set +x
600 dlog 1 "$@"
601 [ -n "$debug" ] && set -x || :
602}
603
604
605# Generic substring function. If $2 is in $1, return 0.
606strstr() { [ "${1#*$2*}" != "$1" ]; }
607
608# normalize_path <path>
609# Prints the normalized path, where it removes any duplicated
610# and trailing slashes.
611# Example:
612# $ normalize_path ///test/test//
613# /test/test
614normalize_path() {
615 shopt -q -s extglob
616 set -- "${1//+(\/)//}"
617 shopt -q -u extglob
618 echo "${1%/}"
619}
620
621# convert_abs_rel <from> <to>
622# Prints the relative path, when creating a symlink to <to> from <from>.
623# Example:
624# $ convert_abs_rel /usr/bin/test /bin/test-2
625# ../../bin/test-2
626# $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
627convert_abs_rel() {
628 local __current __absolute __abssize __cursize __newpath
629 local -i __i __level
630
631 set -- "$(normalize_path "$1")" "$(normalize_path "$2")"
632
633 # corner case #1 - self looping link
634 [[ "$1" == "$2" ]] && { echo "${1##*/}"; return; }
635
636 # corner case #2 - own dir link
637 [[ "${1%/*}" == "$2" ]] && { echo "."; return; }
638
639 IFS="/" __current=($1)
640 IFS="/" __absolute=($2)
641
642 __abssize=${#__absolute[@]}
643 __cursize=${#__current[@]}
644
645 while [[ ${__absolute[__level]} == ${__current[__level]} ]]
646 do
647 (( __level++ ))
648 if (( __level > __abssize || __level > __cursize ))
649 then
650 break
651 fi
652 done
653
654 for ((__i = __level; __i < __cursize-1; __i++))
655 do
656 if ((__i > __level))
657 then
658 __newpath=$__newpath"/"
659 fi
660 __newpath=$__newpath".."
661 done
662
663 for ((__i = __level; __i < __abssize; __i++))
664 do
665 if [[ -n $__newpath ]]
666 then
667 __newpath=$__newpath"/"
668 fi
669 __newpath=$__newpath${__absolute[__i]}
670 done
671
672 echo "$__newpath"
673}
674
675
676# Install a directory, keeping symlinks as on the original system.
677# Example: if /lib points to /lib64 on the host, "inst_dir /lib/file"
678# will create ${initdir}/lib64, ${initdir}/lib64/file,
679# and a symlink ${initdir}/lib -> lib64.
680inst_dir() {
681 [[ -e ${initdir}/"$1" ]] && return 0 # already there
682
683 local _dir="$1" _part="${1%/*}" _file
684 while [[ "$_part" != "${_part%/*}" ]] && ! [[ -e "${initdir}/${_part}" ]]; do
685 _dir="$_part $_dir"
686 _part=${_part%/*}
687 done
688
689 # iterate over parent directories
690 for _file in $_dir; do
691 [[ -e "${initdir}/$_file" ]] && continue
692 if [[ -L $_file ]]; then
693 inst_symlink "$_file"
694 else
695 # create directory
696 mkdir -m 0755 -p "${initdir}/$_file" || return 1
697 [[ -e "$_file" ]] && chmod --reference="$_file" "${initdir}/$_file"
698 chmod u+w "${initdir}/$_file"
699 fi
700 done
701}
702
703# $1 = file to copy to ramdisk
704# $2 (optional) Name for the file on the ramdisk
705# Location of the image dir is assumed to be $initdir
706# We never overwrite the target if it exists.
707inst_simple() {
708 [[ -f "$1" ]] || return 1
709 strstr "$1" "/" || return 1
710
711 local _src=$1 target="${2:-$1}"
712 if ! [[ -d ${initdir}/$target ]]; then
713 [[ -e ${initdir}/$target ]] && return 0
714 [[ -L ${initdir}/$target ]] && return 0
715 [[ -d "${initdir}/${target%/*}" ]] || inst_dir "${target%/*}"
716 fi
717 # install checksum files also
718 if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then
719 inst "${_src%/*}/.${_src##*/}.hmac" "${target%/*}/.${target##*/}.hmac"
720 fi
721 ddebug "Installing $_src"
722 cp --sparse=always -pfL "$_src" "${initdir}/$target"
723}
724
725# find symlinks linked to given library file
726# $1 = library file
727# Function searches for symlinks by stripping version numbers appended to
728# library filename, checks if it points to the same target and finally
729# prints the list of symlinks to stdout.
730#
731# Example:
732# rev_lib_symlinks libfoo.so.8.1
733# output: libfoo.so.8 libfoo.so
734# (Only if libfoo.so.8 and libfoo.so exists on host system.)
735rev_lib_symlinks() {
736 [[ ! $1 ]] && return 0
737
738 local fn="$1" orig="$(readlink -f "$1")" links=''
739
740 [[ ${fn} =~ .*\.so\..* ]] || return 1
741
742 until [[ ${fn##*.} == so ]]; do
743 fn="${fn%.*}"
744 [[ -L ${fn} && $(readlink -f "${fn}") == ${orig} ]] && links+=" ${fn}"
745 done
746
747 echo "${links}"
748}
749
750# Same as above, but specialized to handle dynamic libraries.
751# It handles making symlinks according to how the original library
752# is referenced.
753inst_library() {
754 local _src="$1" _dest=${2:-$1} _lib _reallib _symlink
755 strstr "$1" "/" || return 1
756 [[ -e $initdir/$_dest ]] && return 0
757 if [[ -L $_src ]]; then
758 # install checksum files also
759 if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then
760 inst "${_src%/*}/.${_src##*/}.hmac" "${_dest%/*}/.${_dest##*/}.hmac"
761 fi
762 _reallib=$(readlink -f "$_src")
763 inst_simple "$_reallib" "$_reallib"
764 inst_dir "${_dest%/*}"
765 [[ -d "${_dest%/*}" ]] && _dest=$(readlink -f "${_dest%/*}")/${_dest##*/}
766 ln -sfn $(convert_abs_rel "${_dest}" "${_reallib}") "${initdir}/${_dest}"
767 else
768 inst_simple "$_src" "$_dest"
769 fi
770
771 # Create additional symlinks. See rev_symlinks description.
772 for _symlink in $(rev_lib_symlinks $_src) $(rev_lib_symlinks $_reallib); do
773 [[ ! -e $initdir/$_symlink ]] && {
774 ddebug "Creating extra symlink: $_symlink"
775 inst_symlink $_symlink
776 }
777 done
778}
779
780# find a binary. If we were not passed the full path directly,
781# search in the usual places to find the binary.
782find_binary() {
783 if [[ -z ${1##/*} ]]; then
784 if [[ -x $1 ]] || { strstr "$1" ".so" && ldd $1 &>/dev/null; }; then
785 echo $1
786 return 0
787 fi
788 fi
789
790 type -P $1
791}
792
793# Same as above, but specialized to install binary executables.
794# Install binary executable, and all shared library dependencies, if any.
795inst_binary() {
796 local _bin _target
797 _bin=$(find_binary "$1") || return 1
798 _target=${2:-$_bin}
799 [[ -e $initdir/$_target ]] && return 0
800 [[ -L $_bin ]] && inst_symlink $_bin $_target && return 0
801 local _file _line
802 local _so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
803 # I love bash!
804 LC_ALL=C ldd "$_bin" 2>/dev/null | while read _line; do
805 [[ $_line = 'not a dynamic executable' ]] && break
806
807 if [[ $_line =~ $_so_regex ]]; then
808 _file=${BASH_REMATCH[1]}
809 [[ -e ${initdir}/$_file ]] && continue
810 inst_library "$_file"
811 continue
812 fi
813
814 if [[ $_line =~ not\ found ]]; then
815 dfatal "Missing a shared library required by $_bin."
816 dfatal "Run \"ldd $_bin\" to find out what it is."
817 dfatal "$_line"
818 dfatal "dracut cannot create an initrd."
819 exit 1
820 fi
821 done
822 inst_simple "$_bin" "$_target"
823}
824
825# same as above, except for shell scripts.
826# If your shell script does not start with shebang, it is not a shell script.
827inst_script() {
828 local _bin
829 _bin=$(find_binary "$1") || return 1
830 shift
831 local _line _shebang_regex
832 read -r -n 80 _line <"$_bin"
833 # If debug is set, clean unprintable chars to prevent messing up the term
834 [[ $debug ]] && _line=$(echo -n "$_line" | tr -c -d '[:print:][:space:]')
835 _shebang_regex='(#! *)(/[^ ]+).*'
836 [[ $_line =~ $_shebang_regex ]] || return 1
837 inst "${BASH_REMATCH[2]}" && inst_simple "$_bin" "$@"
838}
839
840# same as above, but specialized for symlinks
841inst_symlink() {
842 local _src=$1 _target=${2:-$1} _realsrc
843 strstr "$1" "/" || return 1
844 [[ -L $1 ]] || return 1
845 [[ -L $initdir/$_target ]] && return 0
846 _realsrc=$(readlink -f "$_src")
847 if ! [[ -e $initdir/$_realsrc ]]; then
848 if [[ -d $_realsrc ]]; then
849 inst_dir "$_realsrc"
850 else
851 inst "$_realsrc"
852 fi
853 fi
854 [[ ! -e $initdir/${_target%/*} ]] && inst_dir "${_target%/*}"
855 [[ -d ${_target%/*} ]] && _target=$(readlink -f ${_target%/*})/${_target##*/}
856 ln -sfn $(convert_abs_rel "${_target}" "${_realsrc}") "$initdir/$_target"
857}
858
859# attempt to install any programs specified in a udev rule
860inst_rule_programs() {
861 local _prog _bin
862
863 if grep -qE 'PROGRAM==?"[^ "]+' "$1"; then
864 for _prog in $(grep -E 'PROGRAM==?"[^ "]+' "$1" | sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/'); do
865 if [ -x /lib/udev/$_prog ]; then
866 _bin=/lib/udev/$_prog
867 else
868 _bin=$(find_binary "$_prog") || {
869 dinfo "Skipping program $_prog using in udev rule $(basename $1) as it cannot be found"
870 continue;
871 }
872 fi
873
874 #dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)"
875 dracut_install "$_bin"
876 done
877 fi
878}
879
880# udev rules always get installed in the same place, so
881# create a function to install them to make life simpler.
882inst_rules() {
883 local _target=/etc/udev/rules.d _rule _found
884
885 inst_dir "/lib/udev/rules.d"
886 inst_dir "$_target"
887 for _rule in "$@"; do
888 if [ "${rule#/}" = "$rule" ]; then
889 for r in /lib/udev/rules.d /etc/udev/rules.d; do
890 if [[ -f $r/$_rule ]]; then
891 _found="$r/$_rule"
892 inst_simple "$_found"
893 inst_rule_programs "$_found"
894 fi
895 done
896 fi
897 for r in '' ./ $dracutbasedir/rules.d/; do
898 if [[ -f ${r}$_rule ]]; then
899 _found="${r}$_rule"
900 inst_simple "$_found" "$_target/${_found##*/}"
901 inst_rule_programs "$_found"
902 fi
903 done
904 [[ $_found ]] || dinfo "Skipping udev rule: $_rule"
905 done
906}
907
908# general purpose installation function
909# Same args as above.
910inst() {
911 local _x
912
913 case $# in
914 1) ;;
915 2) [[ ! $initdir && -d $2 ]] && export initdir=$2
916 [[ $initdir = $2 ]] && set $1;;
917 3) [[ -z $initdir ]] && export initdir=$2
918 set $1 $3;;
919 *) dfatal "inst only takes 1 or 2 or 3 arguments"
920 exit 1;;
921 esac
922 for _x in inst_symlink inst_script inst_binary inst_simple; do
923 $_x "$@" && return 0
924 done
925 return 1
926}
927
928# install any of listed files
929#
930# If first argument is '-d' and second some destination path, first accessible
931# source is installed into this path, otherwise it will installed in the same
932# path as source. If none of listed files was installed, function return 1.
933# On first successful installation it returns with 0 status.
934#
935# Example:
936#
937# inst_any -d /bin/foo /bin/bar /bin/baz
938#
939# Lets assume that /bin/baz exists, so it will be installed as /bin/foo in
940# initramfs.
941inst_any() {
942 local to f
943
944 [[ $1 = '-d' ]] && to="$2" && shift 2
945
946 for f in "$@"; do
947 if [[ -e $f ]]; then
948 [[ $to ]] && inst "$f" "$to" && return 0
949 inst "$f" && return 0
950 fi
951 done
952
953 return 1
954}
955
956# dracut_install [-o ] <file> [<file> ... ]
957# Install <file> to the initramfs image
958# -o optionally install the <file> and don't fail, if it is not there
959dracut_install() {
960 local _optional=no
961 if [[ $1 = '-o' ]]; then
962 _optional=yes
963 shift
964 fi
965 while (($# > 0)); do
966 if ! inst "$1" ; then
967 if [[ $_optional = yes ]]; then
968 dinfo "Skipping program $1 as it cannot be found and is" \
969 "flagged to be optional"
970 else
971 dfatal "Failed to install $1"
972 exit 1
973 fi
974 fi
975 shift
976 done
977}
978
0d6e798a
HH
979# Install a single kernel module along with any firmware it may require.
980# $1 = full path to kernel module to install
981install_kmod_with_fw() {
982 # no need to go further if the module is already installed
983
984 [[ -e "${initdir}/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" ]] \
985 && return 0
986
987 [[ -e "$initdir/.kernelmodseen/${1##*/}" ]] && return 0
988
989 if [[ $omit_drivers ]]; then
990 local _kmod=${1##*/}
991 _kmod=${_kmod%.ko}
992 _kmod=${_kmod/-/_}
993 if [[ "$_kmod" =~ $omit_drivers ]]; then
994 dinfo "Omitting driver $_kmod"
995 return 1
996 fi
997 if [[ "${1##*/lib/modules/$KERNEL_VER/}" =~ $omit_drivers ]]; then
998 dinfo "Omitting driver $_kmod"
999 return 1
1000 fi
1001 fi
1002
1003 [ -d "$initdir/.kernelmodseen" ] && \
1004 > "$initdir/.kernelmodseen/${1##*/}"
1005
1006 inst_simple "$1" "/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" \
1007 || return $?
1008
1009 local _modname=${1##*/} _fwdir _found _fw
1010 _modname=${_modname%.ko*}
1011 for _fw in $(modinfo -k $KERNEL_VER -F firmware $1 2>/dev/null); do
1012 _found=''
1013 for _fwdir in $fw_dir; do
1014 if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then
1015 inst_simple "$_fwdir/$_fw" "/lib/firmware/$_fw"
1016 _found=yes
1017 fi
1018 done
1019 if [[ $_found != yes ]]; then
1020 if ! grep -qe "\<${_modname//-/_}\>" /proc/modules; then
1021 dinfo "Possible missing firmware \"${_fw}\" for kernel module" \
1022 "\"${_modname}.ko\""
1023 else
1024 dwarn "Possible missing firmware \"${_fw}\" for kernel module" \
1025 "\"${_modname}.ko\""
1026 fi
1027 fi
1028 done
1029 return 0
1030}
1031
1032# Do something with all the dependencies of a kernel module.
1033# Note that kernel modules depend on themselves using the technique we use
1034# $1 = function to call for each dependency we find
1035# It will be passed the full path to the found kernel module
1036# $2 = module to get dependencies for
1037# rest of args = arguments to modprobe
1038# _fderr specifies FD passed from surrounding scope
1039for_each_kmod_dep() {
1040 local _func=$1 _kmod=$2 _cmd _modpath _options _found=0
1041 shift 2
1042 modprobe "$@" --ignore-install --show-depends $_kmod 2>&${_fderr} | (
1043 while read _cmd _modpath _options; do
1044 [[ $_cmd = insmod ]] || continue
1045 $_func ${_modpath} || exit $?
1046 _found=1
1047 done
1048 [[ $_found -eq 0 ]] && exit 1
1049 exit 0
1050 )
1051}
1052
1053# filter kernel modules to install certain modules that meet specific
1054# requirements.
1055# $1 = search only in subdirectory of /kernel/$1
1056# $2 = function to call with module name to filter.
1057# This function will be passed the full path to the module to test.
c5315881 1058# The behavior of this function can vary depending on whether $hostonly is set.
0d6e798a
HH
1059# If it is, we will only look at modules that are already in memory.
1060# If it is not, we will look at all kernel modules
1061# This function returns the full filenames of modules that match $1
1062filter_kernel_modules_by_path () (
1063 local _modname _filtercmd
1064 if ! [[ $hostonly ]]; then
1065 _filtercmd='find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra"'
1066 _filtercmd+=' "$KERNEL_MODS/weak-updates" -name "*.ko" -o -name "*.ko.gz"'
1067 _filtercmd+=' -o -name "*.ko.xz"'
1068 _filtercmd+=' 2>/dev/null'
1069 else
1070 _filtercmd='cut -d " " -f 1 </proc/modules|xargs modinfo -F filename '
1071 _filtercmd+='-k $KERNEL_VER 2>/dev/null'
1072 fi
1073 for _modname in $(eval $_filtercmd); do
1074 case $_modname in
1075 *.ko) "$2" "$_modname" && echo "$_modname";;
1076 *.ko.gz) gzip -dc "$_modname" > $initdir/$$.ko
1077 $2 $initdir/$$.ko && echo "$_modname"
1078 rm -f $initdir/$$.ko
1079 ;;
1080 *.ko.xz) xz -dc "$_modname" > $initdir/$$.ko
1081 $2 $initdir/$$.ko && echo "$_modname"
1082 rm -f $initdir/$$.ko
1083 ;;
1084 esac
1085 done
1086)
1087find_kernel_modules_by_path () (
1088 if ! [[ $hostonly ]]; then
1089 find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra" "$KERNEL_MODS/weak-updates" \
1090 -name "*.ko" -o -name "*.ko.gz" -o -name "*.ko.xz" 2>/dev/null
1091 else
1092 cut -d " " -f 1 </proc/modules \
1093 | xargs modinfo -F filename -k $KERNEL_VER 2>/dev/null
1094 fi
1095)
1096
1097filter_kernel_modules () {
1098 filter_kernel_modules_by_path drivers "$1"
1099}
1100
1101find_kernel_modules () {
1102 find_kernel_modules_by_path drivers
1103}
1104
1105# instmods [-c] <kernel module> [<kernel module> ... ]
1106# instmods [-c] <kernel subsystem>
1107# install kernel modules along with all their dependencies.
1108# <kernel subsystem> can be e.g. "=block" or "=drivers/usb/storage"
1109instmods() {
1110 [[ $no_kernel = yes ]] && return
1111 # called [sub]functions inherit _fderr
1112 local _fderr=9
1113 local _check=no
1114 if [[ $1 = '-c' ]]; then
1115 _check=yes
1116 shift
1117 fi
1118
1119 function inst1mod() {
1120 local _ret=0 _mod="$1"
1121 case $_mod in
1122 =*)
1123 if [ -f $KERNEL_MODS/modules.${_mod#=} ]; then
1124 ( [[ "$_mpargs" ]] && echo $_mpargs
1125 cat "${KERNEL_MODS}/modules.${_mod#=}" ) \
1126 | instmods
1127 else
1128 ( [[ "$_mpargs" ]] && echo $_mpargs
1129 find "$KERNEL_MODS" -path "*/${_mod#=}/*" -printf '%f\n' ) \
1130 | instmods
1131 fi
1132 ;;
1133 --*) _mpargs+=" $_mod" ;;
1134 i2o_scsi) return ;; # Do not load this diagnostic-only module
1135 *)
1136 _mod=${_mod##*/}
1137 # if we are already installed, skip this module and go on
1138 # to the next one.
1139 [[ -f "$initdir/.kernelmodseen/${_mod%.ko}.ko" ]] && return
1140
1141 if [[ $omit_drivers ]] && [[ "$1" =~ $omit_drivers ]]; then
1142 dinfo "Omitting driver ${_mod##$KERNEL_MODS}"
1143 return
1144 fi
1145 # If we are building a host-specific initramfs and this
1146 # module is not already loaded, move on to the next one.
1147 [[ $hostonly ]] && ! grep -qe "\<${_mod//-/_}\>" /proc/modules \
1148 && ! echo $add_drivers | grep -qe "\<${_mod}\>" \
1149 && return
1150
1151 # We use '-d' option in modprobe only if modules prefix path
1152 # differs from default '/'. This allows us to use Dracut with
1153 # old version of modprobe which doesn't have '-d' option.
1154 local _moddirname=${KERNEL_MODS%%/lib/modules/*}
1155 [[ -n ${_moddirname} ]] && _moddirname="-d ${_moddirname}/"
1156
1157 # ok, load the module, all its dependencies, and any firmware
1158 # it may require
1159 for_each_kmod_dep install_kmod_with_fw $_mod \
1160 --set-version $KERNEL_VER ${_moddirname} $_mpargs
1161 ((_ret+=$?))
1162 ;;
1163 esac
1164 return $_ret
1165 }
1166
1167 function instmods_1() {
1168 local _mod _mpargs
1169 if (($# == 0)); then # filenames from stdin
1170 while read _mod; do
1171 inst1mod "${_mod%.ko*}" || {
1172 if [ "$_check" = "yes" ]; then
1173 dfatal "Failed to install $_mod"
1174 return 1
1175 fi
1176 }
1177 done
1178 fi
1179 while (($# > 0)); do # filenames as arguments
1180 inst1mod ${1%.ko*} || {
1181 if [ "$_check" = "yes" ]; then
1182 dfatal "Failed to install $1"
1183 return 1
1184 fi
1185 }
1186 shift
1187 done
1188 return 0
1189 }
1190
1191 local _ret _filter_not_found='FATAL: Module .* not found.'
1192 set -o pipefail
1193 # Capture all stderr from modprobe to _fderr. We could use {var}>...
1194 # redirections, but that would make dracut require bash4 at least.
1195 eval "( instmods_1 \"\$@\" ) ${_fderr}>&1" \
1196 | while read line; do [[ "$line" =~ $_filter_not_found ]] && echo $line || echo $line >&2 ;done | derror
1197 _ret=$?
1198 set +o pipefail
1199 return $_ret
1200}
898720b7
HH
1201
1202# inst_libdir_file [-n <pattern>] <file> [<file>...]
1203# Install a <file> located on a lib directory to the initramfs image
1204# -n <pattern> install non-matching files
1205inst_libdir_file() {
1206 if [[ "$1" == "-n" ]]; then
1207 local _pattern=$1
1208 shift 2
1209 for _dir in $libdirs; do
1210 for _i in "$@"; do
1211 for _f in "$_dir"/$_i; do
1212 [[ "$_i" =~ $_pattern ]] || continue
1213 [[ -e "$_i" ]] && dracut_install "$_i"
1214 done
1215 done
1216 done
1217 else
1218 for _dir in $libdirs; do
1219 for _i in "$@"; do
1220 for _f in "$_dir"/$_i; do
1221 [[ -e "$_f" ]] && dracut_install "$_f"
1222 done
1223 done
1224 done
1225 fi
1226}
1227
1ecf6a2b 1228check_nspawn() {
2c393ed7 1229 [[ -d /run/systemd/system ]]
1ecf6a2b
HH
1230}
1231
1232
898720b7 1233do_test() {
33a5e20f
HH
1234 if [[ $UID != "0" ]]; then
1235 echo "TEST: $TEST_DESCRIPTION [SKIPPED]: not root" >&2
1236 exit 0
1237 fi
1238
898720b7
HH
1239# Detect lib paths
1240 [[ $libdir ]] || for libdir in /lib64 /lib; do
1241 [[ -d $libdir ]] && libdirs+=" $libdir" && break
1242 done
1243
1244 [[ $usrlibdir ]] || for usrlibdir in /usr/lib64 /usr/lib; do
1245 [[ -d $usrlibdir ]] && libdirs+=" $usrlibdir" && break
1246 done
1247
1248 import_testdir
889a9042 1249 import_initdir
898720b7
HH
1250
1251 while (($# > 0)); do
1252 case $1 in
1253 --run)
1254 echo "TEST RUN: $TEST_DESCRIPTION"
1255 test_run
1256 ret=$?
1257 if [ $ret -eq 0 ]; then
1258 echo "TEST RUN: $TEST_DESCRIPTION [OK]"
1259 else
1260 echo "TEST RUN: $TEST_DESCRIPTION [FAILED]"
1261 fi
1262 exit $ret;;
1263 --setup)
1264 echo "TEST SETUP: $TEST_DESCRIPTION"
1265 test_setup
1266 exit $?;;
1267 --clean)
1268 echo "TEST CLEANUP: $TEST_DESCRIPTION"
1269 test_cleanup
1270 rm -fr "$TESTDIR"
1271 rm -f .testdir
1272 exit $?;;
1273 --all)
1274 echo -n "TEST: $TEST_DESCRIPTION ";
1275 (
1276 test_setup && test_run
1277 ret=$?
1278 test_cleanup
1279 rm -fr "$TESTDIR"
1280 rm -f .testdir
1281 exit $ret
1282 ) </dev/null >test.log 2>&1
1283 ret=$?
1284 if [ $ret -eq 0 ]; then
1285 rm test.log
1286 echo "[OK]"
1287 else
1288 echo "[FAILED]"
1289 echo "see $(pwd)/test.log"
1290 fi
1291 exit $ret;;
1292 *) break ;;
1293 esac
1294 shift
1295 done
1296}