2 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3 # ex: ts=8 sw=4 sts=4 et filetype=sh
4 PATH
=/sbin
:/bin
:/usr
/sbin
:/usr
/bin
7 LOOKS_LIKE_DEBIAN
=$
(source /etc
/os-release
&& [[ "$ID" = "debian" ||
" $ID_LIKE " = *" debian "* ]] && echo yes || true
)
8 LOOKS_LIKE_ARCH
=$
(source /etc
/os-release
&& [[ "$ID" = "arch" ||
" $ID_LIKE " = *" arch "* ]] && echo yes || true
)
9 LOOKS_LIKE_SUSE
=$
(source /etc
/os-release
&& [[ " $ID_LIKE " = *" suse "* ]] && echo yes || true
)
10 KERNEL_VER
=${KERNEL_VER-$(uname -r)}
11 KERNEL_MODS
="/lib/modules/$KERNEL_VER/"
12 QEMU_TIMEOUT
="${QEMU_TIMEOUT:-infinity}"
13 NSPAWN_TIMEOUT
="${NSPAWN_TIMEOUT:-infinity}"
14 TIMED_OUT
= # will be 1 after run_* if *_TIMEOUT is set and test timed out
15 [[ "$LOOKS_LIKE_SUSE" ]] && FSTYPE
="${FSTYPE:-btrfs}" || FSTYPE
="${FSTYPE:-ext4}"
16 UNIFIED_CGROUP_HIERARCHY
="${UNIFIED_CGROUP_HIERARCHY:-default}"
17 EFI_MOUNT
="$(bootctl -x 2>/dev/null || echo /boot)"
18 QEMU_MEM
="${QEMU_MEM:-512M}"
20 if ! ROOTLIBDIR
=$
(pkg-config
--variable=systemdutildir systemd
); then
21 echo "WARNING! Cannot determine rootlibdir from pkg-config, assuming /usr/lib/systemd" >&2
22 ROOTLIBDIR
=/usr
/lib
/systemd
25 PATH_TO_INIT
=$ROOTLIBDIR/systemd
27 BASICTOOLS
="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo head tail cat mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs"
28 DEBUGTOOLS
="df free ls stty ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find vi mv"
30 STATEDIR
="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))"
31 STATEFILE
="$STATEDIR/.testdir"
32 TESTLOG
="$STATEDIR/test.log"
34 is_built_with_asan
() {
35 if ! type -P objdump
>/dev
/null
; then
36 ddebug
"Failed to find objdump. Assuming systemd hasn't been built with ASAN."
40 # Borrowed from https://github.com/google/oss-fuzz/blob/cd9acd02f9d3f6e80011cc1e9549be526ce5f270/infra/base-images/base-runner/bad_build_check#L182
41 local _asan_calls
=$
(objdump
-dC $BUILD_DIR/systemd-journald |
egrep "callq\s+[0-9a-f]+\s+<__asan" -c)
42 if (( $_asan_calls < 1000 )); then
49 IS_BUILT_WITH_ASAN
=$
(is_built_with_asan
&& echo yes ||
echo no
)
51 if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
53 SKIP_INITRD
="${SKIP_INITRD:-yes}"
54 PATH_TO_INIT
=$ROOTLIBDIR/systemd-under-asan
59 function find_qemu_bin
() {
60 # SUSE and Red Hat call the binary qemu-kvm. Debian and Gentoo call it kvm.
61 # Either way, only use this version if we aren't running in KVM, because
62 # nested KVM is flaky still.
63 if [[ $
(systemd-detect-virt
-v) != kvm
&& -z $TEST_NO_KVM ]] ; then
64 [ "$QEMU_BIN" ] || QEMU_BIN
=$
(which -a kvm qemu-kvm
2>/dev
/null |
grep '^/' -m1)
67 [ "$ARCH" ] || ARCH
=$
(uname
-m)
70 # QEMU's own build system calls it qemu-system-x86_64
71 [ "$QEMU_BIN" ] || QEMU_BIN
=$
(which -a qemu-system-x86_64
2>/dev
/null |
grep '^/' -m1)
74 # new i386 version of QEMU
75 [ "$QEMU_BIN" ] || QEMU_BIN
=$
(which -a qemu-system-i386
2>/dev
/null |
grep '^/' -m1)
77 # i386 version of QEMU
78 [ "$QEMU_BIN" ] || QEMU_BIN
=$
(which -a qemu
2>/dev
/null |
grep '^/' -m1)
81 [ "$QEMU_BIN" ] || QEMU_BIN
=$
(which -a qemu-system-
$ARCH 2>/dev
/null |
grep '^/' -m1)
85 if [ ! -e "$QEMU_BIN" ]; then
86 echo "Could not find a suitable QEMU binary" >&2
91 # Return 0 if QEMU did run (then you must check the result state/logs for actual
92 # success), or 1 if QEMU is not available.
94 if [ -f /etc
/machine-id
]; then
95 read MACHINE_ID
< /etc
/machine-id
96 [ -z "$INITRD" ] && [ -e "$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/initrd" ] \
97 && INITRD
="$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/initrd"
98 [ -z "$KERNEL_BIN" ] && [ -e "$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/linux" ] \
99 && KERNEL_BIN
="$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/linux"
104 if [[ ! "$KERNEL_BIN" ]]; then
105 if [[ "$LOOKS_LIKE_ARCH" ]]; then
106 KERNEL_BIN
=/boot
/vmlinuz-linux
108 [ "$ARCH" ] || ARCH
=$
(uname
-m)
111 KERNEL_BIN
=/boot
/vmlinux-
$KERNEL_VER
115 KERNEL_BIN
=/boot
/vmlinuz-
$KERNEL_VER
121 default_fedora_initrd
=/boot
/initramfs-
${KERNEL_VER}.img
122 default_debian_initrd
=/boot
/initrd.img-
${KERNEL_VER}
123 default_arch_initrd
=/boot
/initramfs-linux-fallback.img
124 default_suse_initrd
=/boot
/initrd-
${KERNEL_VER}
125 if [[ ! "$INITRD" ]]; then
126 if [[ -e "$default_fedora_initrd" ]]; then
127 INITRD
="$default_fedora_initrd"
128 elif [[ "$LOOKS_LIKE_DEBIAN" && -e "$default_debian_initrd" ]]; then
129 INITRD
="$default_debian_initrd"
130 elif [[ "$LOOKS_LIKE_ARCH" && -e "$default_arch_initrd" ]]; then
131 INITRD
="$default_arch_initrd"
132 elif [[ "$LOOKS_LIKE_SUSE" && -e "$default_suse_initrd" ]]; then
133 INITRD
="$default_suse_initrd"
137 # If QEMU_SMP was not explicitly set, try to determine the value 'dynamically'
138 # i.e. use the number of online CPUs on the host machine. If the nproc utility
139 # is not installed or there's some other error when calling it, fall back
140 # to the original value (QEMU_SMP=1).
141 if ! [ "$QEMU_SMP" ]; then
142 if ! QEMU_SMP
=$
(nproc
); then
143 dwarn
"nproc utility is not installed, falling back to QEMU_SMP=1"
148 find_qemu_bin ||
return 1
151 if [[ "$UNIFIED_CGROUP_HIERARCHY" = "yes" ]]; then
152 _cgroup_args
="systemd.unified_cgroup_hierarchy=yes"
153 elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "no" ]]; then
154 _cgroup_args
="systemd.unified_cgroup_hierarchy=no systemd.legacy_systemd_cgroup_controller=yes"
155 elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "hybrid" ]]; then
156 _cgroup_args
="systemd.unified_cgroup_hierarchy=no systemd.legacy_systemd_cgroup_controller=no"
157 elif [[ "$UNIFIED_CGROUP_HIERARCHY" != "default" ]]; then
158 dfatal
"Unknown UNIFIED_CGROUP_HIERARCHY. Got $UNIFIED_CGROUP_HIERARCHY, expected [yes|no|hybrid|default]"
162 if [[ "$LOOKS_LIKE_SUSE" ]]; then
163 PARAMS
+="rd.hostonly=0"
164 elif [[ "$LOOKS_LIKE_ARCH" ]]; then
170 KERNEL_APPEND
="$PARAMS \
182 QEMU_OPTIONS
="-smp $QEMU_SMP \
186 -kernel $KERNEL_BIN \
187 -drive format=raw,cache=unsafe,file=${TESTDIR}/rootdisk.img \
190 if [[ "$INITRD" && "$SKIP_INITRD" != "yes" ]]; then
191 QEMU_OPTIONS
="$QEMU_OPTIONS -initrd $INITRD"
194 # Let's use KVM if it is available, but let's avoid using nested KVM as that is still flaky
195 if [[ -c /dev
/kvm
&& $
(systemd-detect-virt
-v) != kvm
&& -z $TEST_NO_KVM ]] ; then
196 QEMU_OPTIONS
="$QEMU_OPTIONS -machine accel=kvm -enable-kvm -cpu host"
199 if [[ "$QEMU_TIMEOUT" != "infinity" ]]; then
200 QEMU_BIN
="timeout --foreground $QEMU_TIMEOUT $QEMU_BIN"
202 (set -x; $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND")
204 if [ "$rc" = 124 ] && [ "$QEMU_TIMEOUT" != "infinity" ]; then
205 derror
"test timed out after $QEMU_TIMEOUT s"
208 [ "$rc" != 0 ] && derror
"QEMU failed with exit code $rc"
213 # Return 0 if nspawn did run (then you must check the result state/logs for actual
214 # success), or 1 if nspawn is not available.
216 [[ -d /run
/systemd
/system
]] ||
return 1
218 local _nspawn_cmd
="$BUILD_DIR/systemd-nspawn $NSPAWN_ARGUMENTS --register=no --kill-signal=SIGKILL --directory=$TESTDIR/$1 $PATH_TO_INIT $KERNEL_APPEND"
219 if [[ "$NSPAWN_TIMEOUT" != "infinity" ]]; then
220 _nspawn_cmd
="timeout --foreground $NSPAWN_TIMEOUT $_nspawn_cmd"
223 if [[ "$UNIFIED_CGROUP_HIERARCHY" = "hybrid" ]]; then
224 dwarn
"nspawn doesn't support UNIFIED_CGROUP_HIERARCHY=hybrid, skipping"
226 elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "yes" ||
"$UNIFIED_CGROUP_HIERARCHY" = "no" ]]; then
227 _nspawn_cmd
="env UNIFIED_CGROUP_HIERARCHY=$UNIFIED_CGROUP_HIERARCHY $_nspawn_cmd"
228 elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "default" ]]; then
229 _nspawn_cmd
="env --unset=UNIFIED_CGROUP_HIERARCHY $_nspawn_cmd"
231 dfatal
"Unknown UNIFIED_CGROUP_HIERARCHY. Got $UNIFIED_CGROUP_HIERARCHY, expected [yes|no|hybrid|default]"
235 (set -x; $_nspawn_cmd)
237 if [ "$rc" = 124 ] && [ "$NSPAWN_TIMEOUT" != "infinity" ]; then
238 derror
"test timed out after $NSPAWN_TIMEOUT s"
241 [ "$rc" != 0 ] && derror
"nspawn failed with exit code $rc"
246 setup_basic_environment
() {
247 # create the basic filesystem layout
251 install_missing_libraries
269 generate_module_dependencies
270 if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
276 # don't forget KERNEL_APPEND='... selinux=1 ...'
277 if [[ "$SETUP_SELINUX" != "yes" ]]; then
278 ddebug
"Don't setup SELinux"
281 ddebug
"Setup SELinux"
282 local _conf_dir
=/etc
/selinux
283 local _fixfiles_tools
="bash uname cat sort uniq awk grep egrep head expr find rm secon setfiles"
285 rm -rf $initdir/$_conf_dir
286 if ! cp -ar $_conf_dir $initdir/$_conf_dir; then
287 dfatal
"Failed to copy $_conf_dir"
291 cat <<EOF >$initdir/etc/systemd/system/autorelabel.service
293 Description=Relabel all filesystems
294 DefaultDependencies=no
295 Requires=local-fs.target
296 Conflicts=shutdown.target
297 After=local-fs.target
298 Before=sysinit.target shutdown.target
299 ConditionSecurity=selinux
300 ConditionPathExists=|/.autorelabel
303 ExecStart=/bin/sh -x -c 'echo 0 >/sys/fs/selinux/enforce && fixfiles -f -F relabel && rm /.autorelabel && systemctl --force reboot'
309 touch $initdir/.autorelabel
310 mkdir
-p $initdir/etc
/systemd
/system
/basic.target.wants
311 ln -fs autorelabel.service
$initdir/etc
/systemd
/system
/basic.target.wants
/autorelabel.service
313 dracut_install
$_fixfiles_tools
314 dracut_install fixfiles
315 dracut_install sestatus
319 if ! type -p valgrind
; then
320 dfatal
"Failed to install valgrind"
324 local _valgrind_bins
=$
(strace
-e execve valgrind
/bin
/true
2>&1 >/dev
/null | perl
-lne 'print $1 if /^execve\("([^"]+)"/')
325 dracut_install
$_valgrind_bins
327 local _valgrind_libs
=$
(LD_DEBUG
=files valgrind
/bin
/true
2>&1 >/dev
/null | perl
-lne 'print $1 if m{calling init: (/.*vgpreload_.*)}')
328 dracut_install
$_valgrind_libs
330 local _valgrind_dbg_and_supp
=$
(
331 strace
-e open valgrind
/bin
/true
2>&1 >/dev
/null |
332 perl
-lne 'if (my ($fname) = /^open\("([^"]+).*= (?!-)\d+/) { print $fname if $fname =~ /debug|\.supp$/ }'
334 dracut_install
$_valgrind_dbg_and_supp
337 create_valgrind_wrapper
() {
338 local _valgrind_wrapper
=$initdir/$ROOTLIBDIR/systemd-under-valgrind
339 ddebug
"Create $_valgrind_wrapper"
340 cat >$_valgrind_wrapper <<EOF
343 mount -t proc proc /proc
344 exec valgrind --leak-check=full --log-file=/valgrind.out $ROOTLIBDIR/systemd "\$@"
346 chmod 0755 $_valgrind_wrapper
349 create_asan_wrapper
() {
350 local _asan_wrapper
=$initdir/$ROOTLIBDIR/systemd-under-asan
351 ddebug
"Create $_asan_wrapper"
352 cat >$_asan_wrapper <<EOF
357 DEFAULT_ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
358 DEFAULT_UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
359 DEFAULT_ENVIRONMENT="ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS"
361 mount -t proc proc /proc
362 mount -t sysfs sysfs /sys
363 mount -o remount,rw /
365 PATH_TO_ASAN=\$(find / -name '*libasan*' | sed 1q)
366 if [[ "\$PATH_TO_ASAN" ]]; then
367 # A lot of services (most notably dbus) won't start without preloading libasan
368 # See https://github.com/systemd/systemd/issues/5004
369 DEFAULT_ENVIRONMENT="\$DEFAULT_ENVIRONMENT LD_PRELOAD=\$PATH_TO_ASAN"
371 echo DefaultEnvironment=\$DEFAULT_ENVIRONMENT >>/etc/systemd/system.conf
372 echo DefaultTimeoutStartSec=180s >>/etc/systemd/system.conf
374 # ASAN and syscall filters aren't compatible with each other.
375 find / -name '*.service' -type f | xargs sed -i 's/^\\(MemoryDeny\\|SystemCall\\)/#\\1/'
377 # The redirection of ASAN reports to a file prevents them from ending up in /dev/null.
378 # But, apparently, sometimes it doesn't work: https://github.com/google/sanitizers/issues/886.
379 JOURNALD_CONF_DIR=/etc/systemd/system/systemd-journald.service.d
380 mkdir -p "\$JOURNALD_CONF_DIR"
381 printf "[Service]\nEnvironment=ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd-journald.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS:log_path=/systemd-journald.ubsan.log\n" >"\$JOURNALD_CONF_DIR/env.conf"
383 # Sometimes UBSan sends its reports to stderr regardless of what is specified in log_path
384 # Let's try to catch them by redirecting stderr (and stdout just in case) to a file
385 # See https://github.com/systemd/systemd/pull/12524#issuecomment-491108821
386 printf "[Service]\nStandardOutput=file:/systemd-journald.out\n" >"\$JOURNALD_CONF_DIR/out.conf"
388 # 90s isn't enough for some services to finish when literally everything is run
389 # under ASan+UBSan in containers, which, in turn, are run in VMs.
390 # Let's limit which environments such services should be executed in.
391 mkdir -p /etc/systemd/system/systemd-hwdb-update.service.d
392 printf "[Unit]\nConditionVirtualization=container\n\n[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-hwdb-update.service.d/env-override.conf
394 # Let's override another hard-coded timeout that kicks in too early
395 mkdir -p /etc/systemd/system/systemd-journal-flush.service.d
396 printf "[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-journal-flush.service.d/timeout.conf
398 # The 'mount' utility doesn't behave well under libasan, causing unexpected
399 # fails during boot and subsequent test results check:
400 # bash-5.0# mount -o remount,rw -v /
401 # mount: /dev/sda1 mounted on /.
404 # Let's workaround this by clearing the previously set LD_PRELOAD env variable,
405 # so the libasan library is not loaded for this particular service
406 REMOUNTFS_CONF_DIR=/etc/systemd/system/systemd-remount-fs.service.d
407 mkdir -p "\$REMOUNTFS_CONF_DIR"
408 printf "[Service]\nUnsetEnvironment=LD_PRELOAD\n" >"\$REMOUNTFS_CONF_DIR/env.conf"
410 export ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS
411 exec $ROOTLIBDIR/systemd "\$@"
414 chmod 0755 $_asan_wrapper
417 create_strace_wrapper
() {
418 local _strace_wrapper
=$initdir/$ROOTLIBDIR/systemd-under-strace
419 ddebug
"Create $_strace_wrapper"
420 cat >$_strace_wrapper <<EOF
423 exec strace -D -o /strace.out $ROOTLIBDIR/systemd "\$@"
425 chmod 0755 $_strace_wrapper
429 dracut_install
/sbin
/fsck
*
430 dracut_install
-o /bin
/fsck
*
432 # fskc.reiserfs calls reiserfsck. so, install it
433 dracut_install
-o reiserfsck
437 instmods dm_crypt
=crypto
438 type -P dmeventd
>/dev
/null
&& dracut_install dmeventd
439 inst_libdir_file
"libdevmapper-event.so*"
440 if [[ "$LOOKS_LIKE_DEBIAN" ]]; then
441 # dmsetup installs 55-dm and 60-persistent-storage-dm on Debian/Ubuntu
442 # and since buster/bionic 95-dm-notify.rules
443 # see https://gitlab.com/debian-lvm/lvm2/blob/master/debian/patches/udev.patch
444 inst_rules
55-dm.rules
60-persistent-storage-dm.rules
95-dm-notify.rules
446 inst_rules
10-dm.rules
13-dm-disk.rules
95-dm-notify.rules
451 # install compiled files
452 local _ninja_bin
=$
(type -P ninja ||
type -P ninja-build
)
453 if [[ -z "$_ninja_bin" ]]; then
454 dfatal
"ninja was not found"
457 (set -x; DESTDIR
=$initdir "$_ninja_bin" -C $BUILD_DIR install)
458 # remove unneeded documentation
459 rm -fr $initdir/usr
/share
/{man
,doc
}
460 # we strip binaries since debug symbols increase binaries size a lot
461 # and it could fill the available space
464 [[ "$LOOKS_LIKE_SUSE" ]] && setup_suse
466 # enable debug logging in PID1
467 echo LogLevel
=debug
>> $initdir/etc
/systemd
/system.conf
472 objdump
-p "$_bin" 2>/dev
/null |
awk "/R(UN)?PATH/ { print \"$initdir\" \$2 }" |
paste -sd :
475 install_missing_libraries
() {
476 # install possible missing libraries
477 for i
in $initdir{,/usr
}/{sbin
,bin
}/* $initdir{,/usr
}/lib
/systemd
/{,tests
/{,manual
/,unsafe
/}}*; do
478 LD_LIBRARY_PATH
=$
(get_ldpath
$i) inst_libs
$i
482 create_empty_image
() {
484 if [[ "$STRIP_BINARIES" = "no" ]]; then
487 rm -f "$TESTDIR/rootdisk.img"
488 # Create the blank file to use as a root filesystem
489 dd if=/dev
/null of
="$TESTDIR/rootdisk.img" bs
=1M seek
="$_size"
490 LOOPDEV
=$
(losetup
--show -P -f $TESTDIR/rootdisk.img
)
491 [ -b "$LOOPDEV" ] ||
return 1
492 echo "LOOPDEV=$LOOPDEV" >> $STATEFILE
493 sfdisk
"$LOOPDEV" <<EOF
500 local _label
="-L systemd"
501 # mkfs.reiserfs doesn't know -L. so, use --label instead
502 [[ "$FSTYPE" == "reiserfs" ]] && _label
="--label systemd"
503 if ! mkfs
-t "${FSTYPE}" ${_label} "${LOOPDEV}p1" -q; then
504 dfatal
"Failed to mkfs -t ${FSTYPE}"
509 check_asan_reports
() {
513 if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
515 if [[ -e "$root/systemd.asan.log.1" ]]; then
516 cat "$root/systemd.asan.log.1"
520 journald_report
=$
(find "$root" -name "systemd-journald.*san.log*" -exec cat {} \
;)
521 if [[ ! -z "$journald_report" ]]; then
522 printf "%s\n" "$journald_report"
523 cat "$root/systemd-journald.out" || true
528 "$BUILD_DIR/journalctl" -D "$root/var/log/journal" | perl
-alne '
530 %services_to_ignore = (
531 "dbus-daemon" => undef,
534 print $2 if /\s(\S*)\[(\d+)\]:\s*SUMMARY:\s+\w+Sanitizer/ && !exists $services_to_ignore{$1}'
536 if [[ ! -z "$pids" ]]; then
539 "$BUILD_DIR/journalctl" -D "$root/var/log/journal" _PID
=$pid --no-pager
547 check_result_nspawn
() {
549 local journald_report
=""
551 [[ -e $TESTDIR/$1/testok
]] && ret
=0
552 [[ -f $TESTDIR/$1/failed
]] && cp -a $TESTDIR/$1/failed
$TESTDIR
553 cp -a $TESTDIR/$1/var
/log
/journal
$TESTDIR
554 [[ -f $TESTDIR/failed
]] && cat $TESTDIR/failed
555 ls -l $TESTDIR/journal
/*/*.journal
556 test -s $TESTDIR/failed
&& ret
=$
(($ret+1))
557 [ -n "$TIMED_OUT" ] && ret
=$
(($ret+1))
558 check_asan_reports
"$TESTDIR/$1" || ret
=$
(($ret+1))
562 # can be overridden in specific test
563 check_result_qemu
() {
565 mkdir
-p $TESTDIR/root
566 mount
${LOOPDEV}p1
$TESTDIR/root
567 [[ -e $TESTDIR/root
/testok
]] && ret
=0
568 [[ -f $TESTDIR/root
/failed
]] && cp -a $TESTDIR/root
/failed
$TESTDIR
569 cp -a $TESTDIR/root
/var
/log
/journal
$TESTDIR
570 check_asan_reports
"$TESTDIR/root" || ret
=$
(($ret+1))
572 [[ -f $TESTDIR/failed
]] && cat $TESTDIR/failed
573 ls -l $TESTDIR/journal
/*/*.journal
574 test -s $TESTDIR/failed
&& ret
=$
(($ret+1))
575 [ -n "$TIMED_OUT" ] && ret
=$
(($ret+1))
580 if [[ "$STRIP_BINARIES" = "no" ]]; then
581 ddebug
"Don't strip binaries"
584 ddebug
"Strip binaries"
585 find "$initdir" -executable -not -path '*/lib/modules/*.ko' -type f | \
586 xargs strip
--strip-unneeded |
& \
587 grep -v 'file format not recognized' | \
592 mkdir
-p $initdir/etc
/rc.d
593 cat >$initdir/etc
/rc.d
/rc.
local <<EOF
597 chmod 0755 $initdir/etc
/rc.d
/rc.
local
601 ddebug
"install any Execs from the service files"
603 export PKG_CONFIG_PATH
=$BUILD_DIR/src
/core
/
604 systemdsystemunitdir
=$
(pkg-config
--variable=systemdsystemunitdir systemd
)
605 systemduserunitdir
=$
(pkg-config
--variable=systemduserunitdir systemd
)
606 sed -r -n 's|^Exec[a-zA-Z]*=[@+!-]*([^ ]+).*|\1|gp' $initdir/{$systemdsystemunitdir,$systemduserunitdir}/*.service \
607 |
sort -u |
while read i
; do
608 # some {rc,halt}.local scripts and programs are okay to not exist, the rest should
609 # also, plymouth is pulled in by rescue.service, but even there the exit code
610 # is ignored; as it's not present on some distros, don't fail if it doesn't exist
611 inst
$i ||
[ "${i%.local}" != "$i" ] ||
[ "${i%systemd-update-done}" != "$i" ] ||
[ "/bin/plymouth" == "$i" ]
616 generate_module_dependencies
() {
617 if [[ -d $initdir/lib
/modules
/$KERNEL_VER ]] && \
618 ! depmod
-a -b "$initdir" $KERNEL_VER; then
619 dfatal
"\"depmod -a $KERNEL_VER\" failed."
624 install_depmod_files
() {
625 inst
/lib
/modules
/$KERNEL_VER/modules.order
626 inst
/lib
/modules
/$KERNEL_VER/modules.
builtin
630 # install plymouth, if found... else remove plymouth service files
631 # if [ -x /usr/libexec/plymouth/plymouth-populate-initrd ]; then
632 # PLYMOUTH_POPULATE_SOURCE_FUNCTIONS="$TEST_BASE_DIR/test-functions" \
633 # /usr/libexec/plymouth/plymouth-populate-initrd -t $initdir
634 # dracut_install plymouth plymouthd
636 rm -f $initdir/{usr
/lib
,etc
}/systemd
/system
/plymouth
* $initdir/{usr
/lib
,etc
}/systemd
/system
/*/plymouth
*
640 install_ld_so_conf
() {
641 cp -a /etc
/ld.so.conf
* $initdir/etc
642 ldconfig
-r "$initdir"
645 install_config_files
() {
646 inst
/etc
/sysconfig
/init || true
652 inst
/etc
/nsswitch.conf
653 inst
/etc
/pam.conf || true
654 inst
/etc
/securetty || true
657 # we want an empty environment
658 > $initdir/etc
/environment
659 > $initdir/etc
/machine-id
661 echo systemd-testsuite
> $initdir/etc
/hostname
663 if [[ "$LOOKS_LIKE_SUSE" ]]; then
664 ROOTMOUNT
="/dev/sda1 / ${FSTYPE} rw 0 1"
666 ROOTMOUNT
="LABEL=systemd / ${FSTYPE} rw 0 1"
669 cat >$initdir/etc
/fstab
<<EOF
674 install_basic_tools
() {
675 [[ $BASICTOOLS ]] && dracut_install
$BASICTOOLS
676 dracut_install
-o sushell
677 # in Debian ldconfig is just a shell script wrapper around ldconfig.real
678 dracut_install
-o ldconfig.real
681 install_debug_tools
() {
682 [[ $DEBUGTOOLS ]] && dracut_install
$DEBUGTOOLS
684 if [[ $INTERACTIVE_DEBUG ]]; then
685 # Set default TERM from vt220 to linux, so at least basic key shortcuts work
686 local _getty_override
="$initdir/etc/systemd/system/serial-getty@.service.d"
687 mkdir
-p "$_getty_override"
688 echo -e "[Service]\nEnvironment=TERM=linux" > "$_getty_override/default-TERM.conf"
690 cat > "$initdir/etc/motd" << EOF
691 To adjust the terminal size use:
701 # install libnss_files for login
702 NSS_LIBS
=$
(LD_DEBUG
=files getent passwd
2>&1 >/dev
/null |
sed -n '/calling init: .*libnss_/ {s!^.* /!/!; p}')
703 dracut_install
$NSS_LIBS
707 inst
$ROOTLIBDIR/system
/dbus.socket
709 # Newer Fedora versions use dbus-broker by default. Let's install it is available.
710 if [ -f $ROOTLIBDIR/system
/dbus-broker.service
]; then
711 inst
$ROOTLIBDIR/system
/dbus-broker.service
712 inst_symlink
/etc
/systemd
/system
/dbus.service
713 inst
/usr
/bin
/dbus-broker
714 inst
/usr
/bin
/dbus-broker-launch
715 elif [ -f $ROOTLIBDIR/system
/dbus-daemon.service
]; then
716 # Fedora rawhide replaced dbus.service with dbus-daemon.service
717 inst
$ROOTLIBDIR/system
/dbus-daemon.service
719 inst_symlink
/etc
/systemd
/system
/dbus.service
721 inst
$ROOTLIBDIR/system
/dbus.service
725 /etc
/dbus-1
/usr
/share
/dbus-1
-xtype f \
726 |
while read file; do
733 if [[ "$LOOKS_LIKE_DEBIAN" ]] && type -p dpkg-architecture
&>/dev
/null
; then
734 find "/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security" -xtype f
736 find /lib
*/security
-xtype f
738 find /etc
/pam.d
/etc
/security
-xtype f
739 ) |
while read file; do
743 # pam_unix depends on unix_chkpwd.
744 # see http://www.linux-pam.org/Linux-PAM-html/sag-pam_unix.html
745 dracut_install
-o unix_chkpwd
747 [[ "$LOOKS_LIKE_DEBIAN" ]] &&
748 cp /etc
/pam.d
/systemd-user
$initdir/etc
/pam.d
/
750 # set empty root password for easy debugging
751 sed -i 's/^root:x:/root::/' $initdir/etc
/passwd
755 # The first three paths may be deprecated.
756 # It seems now the last two paths are used by many distributions.
758 /usr
/lib
/kbd
/keymaps
/include
/* \
759 /usr
/lib
/kbd
/keymaps
/i386
/include
/* \
760 /usr
/lib
/kbd
/keymaps
/i386
/qwerty
/us.
* \
761 /usr
/lib
/kbd
/keymaps
/legacy
/include
/* \
762 /usr
/lib
/kbd
/keymaps
/legacy
/i386
/qwerty
/us.
*; do
763 [[ -f $i ]] ||
continue
767 # When it takes any argument, then install more keymaps.
770 /usr
/lib
/kbd
/keymaps
/i386
/*/* \
771 /usr
/lib
/kbd
/keymaps
/legacy
/i386
/*/*; do
772 [[ -f $i ]] ||
continue
779 for i
in /usr
/share
/zoneinfo
/{,*/,*/*/}*; do
780 [[ -f $i ]] ||
continue
787 /usr
/lib
/kbd
/consolefonts
/eurlatgr
* \
788 /usr
/lib
/kbd
/consolefonts
/latarcyrheb-sun16
*; do
789 [[ -f $i ]] ||
continue
795 for _terminfodir
in /lib
/terminfo
/etc
/terminfo
/usr
/share
/terminfo
; do
796 [ -f ${_terminfodir}/l
/linux
] && break
798 dracut_install
-o ${_terminfodir}/l
/linux
802 cp $TEST_BASE_DIR/testsuite.target
$initdir/etc
/systemd
/system
/
803 cp $TEST_BASE_DIR/end.service
$initdir/etc
/systemd
/system
/
805 mkdir
-p $initdir/etc
/systemd
/system
/testsuite.target.wants
806 ln -fs $TEST_BASE_DIR/testsuite.service
$initdir/etc
/systemd
/system
/testsuite.target.wants
/testsuite.service
807 # Don't shutdown the machine after running the test when INTERACTIVE_DEBUG is set
808 [[ -z $INTERACTIVE_DEBUG ]] && ln -fs $TEST_BASE_DIR/end.service
$initdir/etc
/systemd
/system
/testsuite.target.wants
/end.service
810 # make the testsuite the default target
811 ln -fs testsuite.target
$initdir/etc
/systemd
/system
/default.target
814 setup_nspawn_root
() {
815 rm -fr $TESTDIR/nspawn-root
816 ddebug
"cp -ar $initdir $TESTDIR/nspawn-root"
817 cp -ar $initdir $TESTDIR/nspawn-root
818 # we don't mount in the nspawn root
819 rm -f $TESTDIR/nspawn-root
/etc
/fstab
820 if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then
821 cp -ar $TESTDIR/nspawn-root
$TESTDIR/unprivileged-nspawn-root
826 mkdir
-p $initdir/run
827 mkdir
-p $initdir/etc
/systemd
/system
828 mkdir
-p $initdir/var
/log
/journal
830 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
831 if [ -L "/$d" ]; then
838 ln -sfn /run
"$initdir/var/run"
839 ln -sfn /run
/lock
"$initdir/var/lock"
844 local _so_regex
='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
847 LC_ALL
=C ldd
"$_bin" 2>/dev
/null |
while read _line
; do
848 [[ $_line = 'not a dynamic executable' ]] && break
850 if [[ $_line =~
$_so_regex ]]; then
851 _file
=${BASH_REMATCH[1]}
852 [[ -e ${initdir}/$_file ]] && continue
853 inst_library
"$_file"
857 if [[ $_line =~ not\ found
]]; then
858 dfatal
"Missing a shared library required by $_bin."
859 dfatal
"Run \"ldd $_bin\" to find out what it is."
861 dfatal
"dracut cannot create an initrd."
868 [[ -e $STATEFILE ]] && .
$STATEFILE
869 if [[ ! -d "$TESTDIR" ]]; then
870 if [[ -z "$TESTDIR" ]]; then
871 TESTDIR
=$
(mktemp
--tmpdir=/var
/tmp
-d -t systemd-test.XXXXXX
)
876 echo "TESTDIR=\"$TESTDIR\"" > $STATEFILE
882 initdir
=$TESTDIR/root
886 ## @brief Converts numeric logging level to the first letter of level name.
888 # @param lvl Numeric logging level in range from 1 to 6.
889 # @retval 1 if @a lvl is out of range.
890 # @retval 0 if @a lvl is correct.
891 # @result Echoes first letter of level name.
904 ## @brief Internal helper function for _do_dlog()
906 # @param lvl Numeric logging level.
907 # @param msg Message.
908 # @retval 0 It's always returned, even if logging failed.
910 # @note This function is not supposed to be called manually. Please use
911 # dtrace(), ddebug(), or others instead which wrap this one.
913 # This function calls _do_dlog() either with parameter msg, or if
914 # none is given, it will read standard input and will use every line as
918 # dwarn "This is a warning"
919 # echo "This is a warning" | dwarn
920 LOG_LEVEL
=${LOG_LEVEL:-4}
923 [ -z "$LOG_LEVEL" ] && return 0
924 [ $1 -le $LOG_LEVEL ] ||
return 0
925 local lvl
="$1"; shift
926 local lvlc
=$
(_lvl2char
"$lvl") ||
return 0
928 if [ $# -ge 1 ]; then
932 echo "$lvlc: " "$line"
937 ## @brief Logs message at TRACE level (6)
939 # @param msg Message.
940 # @retval 0 It's always returned, even if logging failed.
944 [ -n "$debug" ] && set -x ||
:
947 ## @brief Logs message at DEBUG level (5)
949 # @param msg Message.
950 # @retval 0 It's always returned, even if logging failed.
954 # [ -n "$debug" ] && set -x || :
957 ## @brief Logs message at INFO level (4)
959 # @param msg Message.
960 # @retval 0 It's always returned, even if logging failed.
964 [ -n "$debug" ] && set -x ||
:
967 ## @brief Logs message at WARN level (3)
969 # @param msg Message.
970 # @retval 0 It's always returned, even if logging failed.
974 [ -n "$debug" ] && set -x ||
:
977 ## @brief Logs message at ERROR level (2)
979 # @param msg Message.
980 # @retval 0 It's always returned, even if logging failed.
984 # [ -n "$debug" ] && set -x || :
987 ## @brief Logs message at FATAL level (1)
989 # @param msg Message.
990 # @retval 0 It's always returned, even if logging failed.
994 [ -n "$debug" ] && set -x ||
:
998 # Generic substring function. If $2 is in $1, return 0.
999 strstr
() { [ "${1#*$2*}" != "$1" ]; }
1001 # normalize_path <path>
1002 # Prints the normalized path, where it removes any duplicated
1003 # and trailing slashes.
1005 # $ normalize_path ///test/test//
1009 set -- "${1//+(\/)//}"
1014 # convert_abs_rel <from> <to>
1015 # Prints the relative path, when creating a symlink to <to> from <from>.
1017 # $ convert_abs_rel /usr/bin/test /bin/test-2
1019 # $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
1021 local __current __absolute __abssize __cursize __newpath
1022 local -i __i __level
1024 set -- "$(normalize_path "$1")" "$(normalize_path "$2")"
1026 # corner case #1 - self looping link
1027 [[ "$1" == "$2" ]] && { echo "${1##*/}"; return; }
1029 # corner case #2 - own dir link
1030 [[ "${1%/*}" == "$2" ]] && { echo "."; return; }
1032 IFS
="/" __current
=($1)
1033 IFS
="/" __absolute
=($2)
1035 __abssize
=${#__absolute[@]}
1036 __cursize
=${#__current[@]}
1038 while [[ ${__absolute[__level]} == ${__current[__level]} ]]
1041 if (( __level
> __abssize || __level
> __cursize
))
1047 for ((__i
= __level
; __i
< __cursize-1
; __i
++))
1049 if ((__i
> __level
))
1051 __newpath
=$__newpath"/"
1053 __newpath
=$__newpath".."
1056 for ((__i
= __level
; __i
< __abssize
; __i
++))
1058 if [[ -n $__newpath ]]
1060 __newpath
=$__newpath"/"
1062 __newpath
=$__newpath${__absolute[__i]}
1069 # Install a directory, keeping symlinks as on the original system.
1070 # Example: if /lib points to /lib64 on the host, "inst_dir /lib/file"
1071 # will create ${initdir}/lib64, ${initdir}/lib64/file,
1072 # and a symlink ${initdir}/lib -> lib64.
1074 [[ -e ${initdir}/"$1" ]] && return 0 # already there
1076 local _dir
="$1" _part
="${1%/*}" _file
1077 while [[ "$_part" != "${_part%/*}" ]] && ! [[ -e "${initdir}/${_part}" ]]; do
1082 # iterate over parent directories
1083 for _file
in $_dir; do
1084 [[ -e "${initdir}/$_file" ]] && continue
1085 if [[ -L $_file ]]; then
1086 inst_symlink
"$_file"
1089 mkdir
-m 0755 -p "${initdir}/$_file" ||
return 1
1090 [[ -e "$_file" ]] && chmod --reference="$_file" "${initdir}/$_file"
1091 chmod u
+w
"${initdir}/$_file"
1096 # $1 = file to copy to ramdisk
1097 # $2 (optional) Name for the file on the ramdisk
1098 # Location of the image dir is assumed to be $initdir
1099 # We never overwrite the target if it exists.
1101 [[ -f "$1" ]] ||
return 1
1102 strstr
"$1" "/" ||
return 1
1104 local _src
=$1 target
="${2:-$1}"
1105 if ! [[ -d ${initdir}/$target ]]; then
1106 [[ -e ${initdir}/$target ]] && return 0
1107 [[ -L ${initdir}/$target ]] && return 0
1108 [[ -d "${initdir}/${target%/*}" ]] || inst_dir "${target%/*}"
1110 # install checksum files also
1111 if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then
1112 inst
"${_src%/*}/.${_src##*/}.hmac" "${target%/*}/.${target##*/}.hmac"
1114 ddebug
"Installing $_src"
1115 cp --sparse=always
-pfL "$_src" "${initdir}/$target"
1118 # find symlinks linked to given library file
1120 # Function searches for symlinks by stripping version numbers appended to
1121 # library filename, checks if it points to the same target and finally
1122 # prints the list of symlinks to stdout.
1125 # rev_lib_symlinks libfoo.so.8.1
1126 # output: libfoo.so.8 libfoo.so
1127 # (Only if libfoo.so.8 and libfoo.so exists on host system.)
1128 rev_lib_symlinks
() {
1129 [[ ! $1 ]] && return 0
1131 local fn
="$1" orig
="$(readlink -f "$1")" links
=''
1133 [[ ${fn} =~ .
*\.so\..
* ]] ||
return 1
1135 until [[ ${fn##*.} == so
]]; do
1137 [[ -L ${fn} && $(readlink -f "${fn}") == ${orig} ]] && links+=" ${fn}"
1143 # Same as above, but specialized to handle dynamic libraries.
1144 # It handles making symlinks according to how the original library
1147 local _src="$1" _dest=${2:-$1} _lib _reallib _symlink
1148 strstr "$1" "/" || return 1
1149 [[ -e $initdir/$_dest ]] && return 0
1150 if [[ -L $_src ]]; then
1151 # install checksum files also
1152 if [[ -e "${_src%/*}/.
${_src##*/}.hmac
" ]]; then
1153 inst "${_src%/*}/.${_src##*/}.hmac" "${_dest%/*}/.${_dest##*/}.hmac
"
1155 _reallib=$(readlink -f "$_src")
1156 inst_simple "$_reallib" "$_reallib"
1157 inst_dir "${_dest%/*}"
1158 [[ -d "${_dest%/*}" ]] && _dest=$(readlink -f "${_dest%/*}")/${_dest##*/}
1159 ln -sfn $
(convert_abs_rel
"${_dest}" "${_reallib}") "${initdir}/${_dest}"
1161 inst_simple
"$_src" "$_dest"
1164 # Create additional symlinks. See rev_symlinks description.
1165 for _symlink
in $
(rev_lib_symlinks
$_src) $
(rev_lib_symlinks
$_reallib); do
1166 [[ -e $initdir/$_symlink ]] ||
{
1167 ddebug
"Creating extra symlink: $_symlink"
1168 inst_symlink
$_symlink
1173 # find a binary. If we were not passed the full path directly,
1174 # search in the usual places to find the binary.
1176 if [[ -z ${1##/*} ]]; then
1177 if [[ -x $1 ]] ||
{ strstr
"$1" ".so" && ldd
$1 &>/dev
/null
; }; then
1186 # Same as above, but specialized to install binary executables.
1187 # Install binary executable, and all shared library dependencies, if any.
1190 _bin
=$
(find_binary
"$1") ||
return 1
1192 [[ -e $initdir/$_target ]] && return 0
1193 [[ -L $_bin ]] && inst_symlink
$_bin $_target && return 0
1195 local _so_regex
='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
1197 LC_ALL
=C ldd
"$_bin" 2>/dev
/null |
while read _line
; do
1198 [[ $_line = 'not a dynamic executable' ]] && break
1200 if [[ $_line =~
$_so_regex ]]; then
1201 _file
=${BASH_REMATCH[1]}
1202 [[ -e ${initdir}/$_file ]] && continue
1203 inst_library
"$_file"
1207 if [[ $_line =~ not\ found
]]; then
1208 dfatal
"Missing a shared library required by $_bin."
1209 dfatal
"Run \"ldd $_bin\" to find out what it is."
1211 dfatal
"dracut cannot create an initrd."
1215 inst_simple
"$_bin" "$_target"
1218 # same as above, except for shell scripts.
1219 # If your shell script does not start with shebang, it is not a shell script.
1222 _bin
=$
(find_binary
"$1") ||
return 1
1224 local _line _shebang_regex
1225 read -r -n 80 _line
<"$_bin"
1226 # If debug is set, clean unprintable chars to prevent messing up the term
1227 [[ $debug ]] && _line
=$
(echo -n "$_line" |
tr -c -d '[:print:][:space:]')
1228 _shebang_regex
='(#! *)(/[^ ]+).*'
1229 [[ $_line =~
$_shebang_regex ]] ||
return 1
1230 inst
"${BASH_REMATCH[2]}" && inst_simple
"$_bin" "$@"
1233 # same as above, but specialized for symlinks
1235 local _src
=$1 _target
=${2:-$1} _realsrc
1236 strstr
"$1" "/" ||
return 1
1237 [[ -L $1 ]] ||
return 1
1238 [[ -L $initdir/$_target ]] && return 0
1239 _realsrc
=$
(readlink
-f "$_src")
1240 if ! [[ -e $initdir/$_realsrc ]]; then
1241 if [[ -d $_realsrc ]]; then
1242 inst_dir
"$_realsrc"
1247 [[ ! -e $initdir/${_target%/*} ]] && inst_dir
"${_target%/*}"
1248 [[ -d ${_target%/*} ]] && _target=$(readlink -f ${_target%/*})/${_target##*/}
1249 ln -sfn $
(convert_abs_rel
"${_target}" "${_realsrc}") "$initdir/$_target"
1252 # attempt to install any programs specified in a udev rule
1253 inst_rule_programs
() {
1256 if grep -qE 'PROGRAM==?"[^ "]+' "$1"; then
1257 for _prog
in $
(grep -E 'PROGRAM==?"[^ "]+' "$1" |
sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/'); do
1258 if [ -x /lib
/udev
/$_prog ]; then
1259 _bin
=/lib
/udev
/$_prog
1261 _bin
=$
(find_binary
"$_prog") ||
{
1262 dinfo
"Skipping program $_prog using in udev rule $(basename $1) as it cannot be found"
1267 #dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)"
1268 dracut_install
"$_bin"
1273 # udev rules always get installed in the same place, so
1274 # create a function to install them to make life simpler.
1276 local _target
=/etc
/udev
/rules.d _rule _found
1278 inst_dir
"/lib/udev/rules.d"
1280 for _rule
in "$@"; do
1281 if [ "${rule#/}" = "$rule" ]; then
1282 for r
in /lib
/udev
/rules.d
/etc
/udev
/rules.d
; do
1283 if [[ -f $r/$_rule ]]; then
1285 inst_simple
"$_found"
1286 inst_rule_programs
"$_found"
1290 for r
in '' .
/ $dracutbasedir/rules.d
/; do
1291 if [[ -f ${r}$_rule ]]; then
1293 inst_simple
"$_found" "$_target/${_found##*/}"
1294 inst_rule_programs
"$_found"
1297 [[ $_found ]] || dinfo
"Skipping udev rule: $_rule"
1302 # general purpose installation function
1303 # Same args as above.
1309 2) [[ ! $initdir && -d $2 ]] && export initdir
=$2
1310 [[ $initdir = $2 ]] && set $1;;
1311 3) [[ -z $initdir ]] && export initdir
=$2
1313 *) dfatal
"inst only takes 1 or 2 or 3 arguments"
1316 for _x
in inst_symlink inst_script inst_binary inst_simple
; do
1317 $_x "$@" && return 0
1322 # install any of listed files
1324 # If first argument is '-d' and second some destination path, first accessible
1325 # source is installed into this path, otherwise it will installed in the same
1326 # path as source. If none of listed files was installed, function return 1.
1327 # On first successful installation it returns with 0 status.
1331 # inst_any -d /bin/foo /bin/bar /bin/baz
1333 # Lets assume that /bin/baz exists, so it will be installed as /bin/foo in
1338 [[ $1 = '-d' ]] && to
="$2" && shift 2
1341 if [[ -e $f ]]; then
1342 [[ $to ]] && inst
"$f" "$to" && return 0
1343 inst
"$f" && return 0
1350 # dracut_install [-o ] <file> [<file> ... ]
1351 # Install <file> to the initramfs image
1352 # -o optionally install the <file> and don't fail, if it is not there
1355 if [[ $1 = '-o' ]]; then
1359 while (($# > 0)); do
1360 if ! inst
"$1" ; then
1361 if [[ $_optional = yes ]]; then
1362 dinfo
"Skipping program $1 as it cannot be found and is" \
1363 "flagged to be optional"
1365 dfatal
"Failed to install $1"
1373 # Install a single kernel module along with any firmware it may require.
1374 # $1 = full path to kernel module to install
1375 install_kmod_with_fw
() {
1376 # no need to go further if the module is already installed
1378 [[ -e "${initdir}/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" ]] \
1381 [[ -e "$initdir/.kernelmodseen/${1##*/}" ]] && return 0
1383 if [[ $omit_drivers ]]; then
1384 local _kmod
=${1##*/}
1387 if [[ "$_kmod" =~
$omit_drivers ]]; then
1388 dinfo
"Omitting driver $_kmod"
1391 if [[ "${1##*/lib/modules/$KERNEL_VER/}" =~
$omit_drivers ]]; then
1392 dinfo
"Omitting driver $_kmod"
1397 [ -d "$initdir/.kernelmodseen" ] && \
1398 > "$initdir/.kernelmodseen/${1##*/}"
1400 inst_simple
"$1" "/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" \
1403 local _modname
=${1##*/} _fwdir _found _fw
1404 _modname
=${_modname%.ko*}
1405 for _fw
in $
(modinfo
-k $KERNEL_VER -F firmware
$1 2>/dev
/null
); do
1407 for _fwdir
in $fw_dir; do
1408 if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then
1409 inst_simple
"$_fwdir/$_fw" "/lib/firmware/$_fw"
1413 if [[ $_found != yes ]]; then
1414 if ! grep -qe "\<${_modname//-/_}\>" /proc
/modules
; then
1415 dinfo
"Possible missing firmware \"${_fw}\" for kernel module" \
1416 "\"${_modname}.ko\""
1418 dwarn
"Possible missing firmware \"${_fw}\" for kernel module" \
1419 "\"${_modname}.ko\""
1426 # Do something with all the dependencies of a kernel module.
1427 # Note that kernel modules depend on themselves using the technique we use
1428 # $1 = function to call for each dependency we find
1429 # It will be passed the full path to the found kernel module
1430 # $2 = module to get dependencies for
1431 # rest of args = arguments to modprobe
1432 # _fderr specifies FD passed from surrounding scope
1433 for_each_kmod_dep
() {
1434 local _func
=$1 _kmod
=$2 _cmd _modpath _options _found
=0
1436 modprobe
"$@" --ignore-install --show-depends $_kmod 2>&${_fderr} |
(
1437 while read _cmd _modpath _options
; do
1438 [[ $_cmd = insmod
]] ||
continue
1439 $_func ${_modpath} ||
exit $?
1442 [[ $_found -eq 0 ]] && exit 1
1447 # filter kernel modules to install certain modules that meet specific
1449 # $1 = search only in subdirectory of /kernel/$1
1450 # $2 = function to call with module name to filter.
1451 # This function will be passed the full path to the module to test.
1452 # The behavior of this function can vary depending on whether $hostonly is set.
1453 # If it is, we will only look at modules that are already in memory.
1454 # If it is not, we will look at all kernel modules
1455 # This function returns the full filenames of modules that match $1
1456 filter_kernel_modules_by_path
() (
1457 local _modname _filtercmd
1458 if ! [[ $hostonly ]]; then
1459 _filtercmd
='find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra"'
1460 _filtercmd
+=' "$KERNEL_MODS/weak-updates" -name "*.ko" -o -name "*.ko.gz"'
1461 _filtercmd
+=' -o -name "*.ko.xz"'
1462 _filtercmd
+=' 2>/dev/null'
1464 _filtercmd
='cut -d " " -f 1 </proc/modules|xargs modinfo -F filename '
1465 _filtercmd
+='-k $KERNEL_VER 2>/dev/null'
1467 for _modname
in $
(eval $_filtercmd); do
1469 *.ko
) "$2" "$_modname" && echo "$_modname";;
1470 *.ko.gz
) gzip -dc "$_modname" > $initdir/$$.ko
1471 $2 $initdir/$$.ko
&& echo "$_modname"
1472 rm -f $initdir/$$.ko
1474 *.ko.xz
) xz
-dc "$_modname" > $initdir/$$.ko
1475 $2 $initdir/$$.ko
&& echo "$_modname"
1476 rm -f $initdir/$$.ko
1481 find_kernel_modules_by_path
() (
1482 if ! [[ $hostonly ]]; then
1483 find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra" "$KERNEL_MODS/weak-updates" \
1484 -name "*.ko" -o -name "*.ko.gz" -o -name "*.ko.xz" 2>/dev
/null
1486 cut
-d " " -f 1 </proc
/modules \
1487 |
xargs modinfo
-F filename
-k $KERNEL_VER 2>/dev
/null
1491 filter_kernel_modules
() {
1492 filter_kernel_modules_by_path drivers
"$1"
1495 find_kernel_modules
() {
1496 find_kernel_modules_by_path drivers
1499 # instmods [-c] <kernel module> [<kernel module> ... ]
1500 # instmods [-c] <kernel subsystem>
1501 # install kernel modules along with all their dependencies.
1502 # <kernel subsystem> can be e.g. "=block" or "=drivers/usb/storage"
1504 [[ $no_kernel = yes ]] && return
1505 # called [sub]functions inherit _fderr
1508 if [[ $1 = '-c' ]]; then
1513 function inst1mod
() {
1514 local _ret
=0 _mod
="$1"
1517 if [ -f $KERNEL_MODS/modules.
${_mod#=} ]; then
1518 ( [[ "$_mpargs" ]] && echo $_mpargs
1519 cat "${KERNEL_MODS}/modules.${_mod#=}" ) \
1522 ( [[ "$_mpargs" ]] && echo $_mpargs
1523 find "$KERNEL_MODS" -path "*/${_mod#=}/*" -printf '%f\n' ) \
1527 --*) _mpargs
+=" $_mod" ;;
1528 i2o_scsi
) return ;; # Do not load this diagnostic-only module
1531 # if we are already installed, skip this module and go on
1533 [[ -f "$initdir/.kernelmodseen/${_mod%.ko}.ko" ]] && return
1535 if [[ $omit_drivers ]] && [[ "$1" =~
$omit_drivers ]]; then
1536 dinfo
"Omitting driver ${_mod##$KERNEL_MODS}"
1539 # If we are building a host-specific initramfs and this
1540 # module is not already loaded, move on to the next one.
1541 [[ $hostonly ]] && ! grep -qe "\<${_mod//-/_}\>" /proc
/modules \
1542 && ! echo $add_drivers |
grep -qe "\<${_mod}\>" \
1545 # We use '-d' option in modprobe only if modules prefix path
1546 # differs from default '/'. This allows us to use Dracut with
1547 # old version of modprobe which doesn't have '-d' option.
1548 local _moddirname
=${KERNEL_MODS%%/lib/modules/*}
1549 [[ -n ${_moddirname} ]] && _moddirname
="-d ${_moddirname}/"
1551 # ok, load the module, all its dependencies, and any firmware
1553 for_each_kmod_dep install_kmod_with_fw
$_mod \
1554 --set-version $KERNEL_VER ${_moddirname} $_mpargs
1561 function instmods_1
() {
1563 if (($# == 0)); then # filenames from stdin
1565 inst1mod
"${_mod%.ko*}" ||
{
1566 if [ "$_check" = "yes" ]; then
1567 dfatal
"Failed to install $_mod"
1573 while (($# > 0)); do # filenames as arguments
1574 inst1mod
${1%.ko*} ||
{
1575 if [ "$_check" = "yes" ]; then
1576 dfatal
"Failed to install $1"
1585 local _ret _filter_not_found
='FATAL: Module .* not found.'
1587 # Capture all stderr from modprobe to _fderr. We could use {var}>...
1588 # redirections, but that would make dracut require bash4 at least.
1589 eval "( instmods_1 \"\$@\" ) ${_fderr}>&1" \
1590 |
while read line
; do [[ "$line" =~
$_filter_not_found ]] && echo $line ||
echo $line >&2 ;done | derror
1596 # inst_libdir_file [-n <pattern>] <file> [<file>...]
1597 # Install a <file> located on a lib directory to the initramfs image
1598 # -n <pattern> install non-matching files
1599 inst_libdir_file
() {
1600 if [[ "$1" == "-n" ]]; then
1603 for _dir
in $libdirs; do
1605 for _f
in "$_dir"/$_i; do
1606 [[ "$_i" =~
$_pattern ]] ||
continue
1607 [[ -e "$_i" ]] && dracut_install
"$_i"
1612 for _dir
in $libdirs; do
1614 for _f
in "$_dir"/$_i; do
1615 [[ -e "$_f" ]] && dracut_install
"$_f"
1623 ln -fs ..
/usr
/bin
/systemctl
$initdir/bin
/
1624 ln -fs ..
/usr
/lib
/systemd
$initdir/lib
/
1625 inst_simple
"/usr/lib/systemd/system/haveged.service"
1628 # can be overridden in specific test
1630 umount
$TESTDIR/root
2>/dev
/null || true
1631 [[ $LOOPDEV ]] && losetup
-d $LOOPDEV || true
1636 if [ -z "$TEST_NO_QEMU" ]; then
1638 check_result_qemu ||
return 1
1640 dwarn
"can't run QEMU, skipping"
1643 if [ -z "$TEST_NO_NSPAWN" ]; then
1644 if run_nspawn
"nspawn-root"; then
1645 check_result_nspawn
"nspawn-root" ||
return 1
1647 dwarn
"can't run systemd-nspawn, skipping"
1650 if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then
1651 if NSPAWN_ARGUMENTS
="-U --private-network $NSPAWN_ARGUMENTS" run_nspawn
"unprivileged-nspawn-root"; then
1652 check_result_nspawn
"unprivileged-nspawn-root" ||
return 1
1654 dwarn
"can't run systemd-nspawn, skipping"
1662 if [[ $UID != "0" ]]; then
1663 echo "TEST: $TEST_DESCRIPTION [SKIPPED]: not root" >&2
1668 [[ $libdir ]] ||
for libdir
in /lib64
/lib
; do
1669 [[ -d $libdir ]] && libdirs
+=" $libdir" && break
1672 [[ $usrlibdir ]] ||
for usrlibdir
in /usr
/lib64
/usr
/lib
; do
1673 [[ -d $usrlibdir ]] && libdirs
+=" $usrlibdir" && break
1676 mkdir
-p "$STATEDIR"
1681 while (($# > 0)); do
1684 echo "TEST RUN: $TEST_DESCRIPTION"
1687 if (( $ret == 0 )); then
1688 echo "TEST RUN: $TEST_DESCRIPTION [OK]"
1690 echo "TEST RUN: $TEST_DESCRIPTION [FAILED]"
1694 echo "TEST SETUP: $TEST_DESCRIPTION"
1698 echo "TEST CLEANUP: $TEST_DESCRIPTION"
1705 echo -n "TEST: $TEST_DESCRIPTION ";
1707 test_setup
&& test_run
1713 ) </dev
/null
>"$TESTLOG" 2>&1 || ret
=$?
1714 if [ $ret -eq 0 ]; then