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