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