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 -p 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
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\n" >"\$JOURNALD_CONF_DIR/env.conf"
383 # 90s isn't enough for some services to finish when literally everything is run
384 # under ASan+UBSan in containers, which, in turn, are run in VMs.
385 # Let's limit which environments such services should be executed in.
386 mkdir -p /etc/systemd/system/systemd-hwdb-update.service.d
387 printf "[Unit]\nConditionVirtualization=container\n\n[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-hwdb-update.service.d/env-override.conf
389 export ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS
390 exec $ROOTLIBDIR/systemd "\$@"
393 chmod 0755 $_asan_wrapper
396 create_strace_wrapper
() {
397 local _strace_wrapper
=$initdir/$ROOTLIBDIR/systemd-under-strace
398 ddebug
"Create $_strace_wrapper"
399 cat >$_strace_wrapper <<EOF
402 exec strace -D -o /strace.out $ROOTLIBDIR/systemd "\$@"
404 chmod 0755 $_strace_wrapper
408 dracut_install
/sbin
/fsck
*
409 dracut_install
-o /bin
/fsck
*
411 # fskc.reiserfs calls reiserfsck. so, install it
412 dracut_install
-o reiserfsck
416 instmods dm_crypt
=crypto
417 type -P dmeventd
>/dev
/null
&& dracut_install dmeventd
418 inst_libdir_file
"libdevmapper-event.so*"
419 if [[ "$LOOKS_LIKE_DEBIAN" ]]; then
420 # dmsetup installs 55-dm and 60-persistent-storage-dm on Debian/Ubuntu
421 # and since buster/bionic 95-dm-notify.rules
422 # see https://gitlab.com/debian-lvm/lvm2/blob/master/debian/patches/udev.patch
423 inst_rules
55-dm.rules
60-persistent-storage-dm.rules
95-dm-notify.rules
425 inst_rules
10-dm.rules
13-dm-disk.rules
95-dm-notify.rules
430 # install compiled files
431 local _ninja_bin
=$
(type -P ninja ||
type -P ninja-build
)
432 if [[ -z "$_ninja_bin" ]]; then
433 dfatal
"ninja was not found"
436 (set -x; DESTDIR
=$initdir "$_ninja_bin" -C $BUILD_DIR install)
437 # remove unneeded documentation
438 rm -fr $initdir/usr
/share
/{man
,doc
}
439 # we strip binaries since debug symbols increase binaries size a lot
440 # and it could fill the available space
443 [[ "$LOOKS_LIKE_SUSE" ]] && setup_suse
445 # enable debug logging in PID1
446 echo LogLevel
=debug
>> $initdir/etc
/systemd
/system.conf
451 objdump
-p "$_bin" 2>/dev
/null |
awk "/R(UN)?PATH/ { print \"$initdir\" \$2 }" |
paste -sd :
454 install_missing_libraries
() {
455 # install possible missing libraries
456 for i
in $initdir{,/usr
}/{sbin
,bin
}/* $initdir{,/usr
}/lib
/systemd
/{,tests
/{,manual
/,unsafe
/}}*; do
457 LD_LIBRARY_PATH
=$
(get_ldpath
$i) inst_libs
$i
461 create_empty_image
() {
463 if [[ "$STRIP_BINARIES" = "no" ]]; then
466 rm -f "$TESTDIR/rootdisk.img"
467 # Create the blank file to use as a root filesystem
468 dd if=/dev
/null of
="$TESTDIR/rootdisk.img" bs
=1M seek
="$_size"
469 LOOPDEV
=$
(losetup
--show -P -f $TESTDIR/rootdisk.img
)
470 [ -b "$LOOPDEV" ] ||
return 1
471 echo "LOOPDEV=$LOOPDEV" >> $STATEFILE
472 sfdisk
"$LOOPDEV" <<EOF
479 local _label
="-L systemd"
480 # mkfs.reiserfs doesn't know -L. so, use --label instead
481 [[ "$FSTYPE" == "reiserfs" ]] && _label
="--label systemd"
482 if ! mkfs
-t "${FSTYPE}" ${_label} "${LOOPDEV}p1" -q; then
483 dfatal
"Failed to mkfs -t ${FSTYPE}"
488 check_asan_reports
() {
492 if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
494 if [[ -e "$root/systemd.asan.log.1" ]]; then
495 cat "$root/systemd.asan.log.1"
499 journald_report
=$
(find "$root" -name "systemd-journald.asan.log*" -exec cat {} \
;)
500 if [[ ! -z "$journald_report" ]]; then
501 printf "%s" "$journald_report"
506 "$BUILD_DIR/journalctl" -D "$root/var/log/journal" | perl
-alne '
508 %services_to_ignore = (
509 "dbus-daemon" => undef,
512 print $2 if /\s(\S*)\[(\d+)\]:\s*SUMMARY:\s+\w+Sanitizer/ && !exists $services_to_ignore{$1}'
514 if [[ ! -z "$pids" ]]; then
517 "$BUILD_DIR/journalctl" -D "$root/var/log/journal" _PID
=$pid --no-pager
525 check_result_nspawn
() {
527 local journald_report
=""
529 [[ -e $TESTDIR/$1/testok
]] && ret
=0
530 [[ -f $TESTDIR/$1/failed
]] && cp -a $TESTDIR/$1/failed
$TESTDIR
531 cp -a $TESTDIR/$1/var
/log
/journal
$TESTDIR
532 [[ -f $TESTDIR/failed
]] && cat $TESTDIR/failed
533 ls -l $TESTDIR/journal
/*/*.journal
534 test -s $TESTDIR/failed
&& ret
=$
(($ret+1))
535 [ -n "$TIMED_OUT" ] && ret
=$
(($ret+1))
536 check_asan_reports
"$TESTDIR/$1" || ret
=$
(($ret+1))
540 # can be overridden in specific test
541 check_result_qemu
() {
543 mkdir
-p $TESTDIR/root
544 mount
${LOOPDEV}p1
$TESTDIR/root
545 [[ -e $TESTDIR/root
/testok
]] && ret
=0
546 [[ -f $TESTDIR/root
/failed
]] && cp -a $TESTDIR/root
/failed
$TESTDIR
547 cp -a $TESTDIR/root
/var
/log
/journal
$TESTDIR
548 check_asan_reports
"$TESTDIR/root" || ret
=$
(($ret+1))
550 [[ -f $TESTDIR/failed
]] && cat $TESTDIR/failed
551 ls -l $TESTDIR/journal
/*/*.journal
552 test -s $TESTDIR/failed
&& ret
=$
(($ret+1))
553 [ -n "$TIMED_OUT" ] && ret
=$
(($ret+1))
558 if [[ "$STRIP_BINARIES" = "no" ]]; then
559 ddebug
"Don't strip binaries"
562 ddebug
"Strip binaries"
563 find "$initdir" -executable -not -path '*/lib/modules/*.ko' -type f | \
564 xargs strip
--strip-unneeded |
& \
565 grep -v 'file format not recognized' | \
570 mkdir
-p $initdir/etc
/rc.d
571 cat >$initdir/etc
/rc.d
/rc.
local <<EOF
575 chmod 0755 $initdir/etc
/rc.d
/rc.
local
579 ddebug
"install any Execs from the service files"
581 export PKG_CONFIG_PATH
=$BUILD_DIR/src
/core
/
582 systemdsystemunitdir
=$
(pkg-config
--variable=systemdsystemunitdir systemd
)
583 systemduserunitdir
=$
(pkg-config
--variable=systemduserunitdir systemd
)
584 sed -r -n 's|^Exec[a-zA-Z]*=[@+!-]*([^ ]+).*|\1|gp' $initdir/{$systemdsystemunitdir,$systemduserunitdir}/*.service \
585 |
sort -u |
while read i
; do
586 # some {rc,halt}.local scripts and programs are okay to not exist, the rest should
587 # also, plymouth is pulled in by rescue.service, but even there the exit code
588 # is ignored; as it's not present on some distros, don't fail if it doesn't exist
589 inst
$i ||
[ "${i%.local}" != "$i" ] ||
[ "${i%systemd-update-done}" != "$i" ] ||
[ "/bin/plymouth" == "$i" ]
594 generate_module_dependencies
() {
595 if [[ -d $initdir/lib
/modules
/$KERNEL_VER ]] && \
596 ! depmod
-a -b "$initdir" $KERNEL_VER; then
597 dfatal
"\"depmod -a $KERNEL_VER\" failed."
602 install_depmod_files
() {
603 inst
/lib
/modules
/$KERNEL_VER/modules.order
604 inst
/lib
/modules
/$KERNEL_VER/modules.
builtin
608 # install plymouth, if found... else remove plymouth service files
609 # if [ -x /usr/libexec/plymouth/plymouth-populate-initrd ]; then
610 # PLYMOUTH_POPULATE_SOURCE_FUNCTIONS="$TEST_BASE_DIR/test-functions" \
611 # /usr/libexec/plymouth/plymouth-populate-initrd -t $initdir
612 # dracut_install plymouth plymouthd
614 rm -f $initdir/{usr
/lib
,etc
}/systemd
/system
/plymouth
* $initdir/{usr
/lib
,etc
}/systemd
/system
/*/plymouth
*
618 install_ld_so_conf
() {
619 cp -a /etc
/ld.so.conf
* $initdir/etc
620 ldconfig
-r "$initdir"
623 install_config_files
() {
624 inst
/etc
/sysconfig
/init || true
630 inst
/etc
/nsswitch.conf
631 inst
/etc
/pam.conf || true
632 inst
/etc
/securetty || true
635 # we want an empty environment
636 > $initdir/etc
/environment
637 > $initdir/etc
/machine-id
639 echo systemd-testsuite
> $initdir/etc
/hostname
641 if [[ "$LOOKS_LIKE_SUSE" ]]; then
642 ROOTMOUNT
="/dev/sda1 / ${FSTYPE} rw 0 1"
644 ROOTMOUNT
="LABEL=systemd / ${FSTYPE} rw 0 1"
647 cat >$initdir/etc
/fstab
<<EOF
652 install_basic_tools
() {
653 [[ $BASICTOOLS ]] && dracut_install
$BASICTOOLS
654 dracut_install
-o sushell
655 # in Debian ldconfig is just a shell script wrapper around ldconfig.real
656 dracut_install
-o ldconfig.real
659 install_debug_tools
() {
660 [[ $DEBUGTOOLS ]] && dracut_install
$DEBUGTOOLS
662 if [[ $INTERACTIVE_DEBUG ]]; then
663 # Set default TERM from vt220 to linux, so at least basic key shortcuts work
664 local _getty_override
="$initdir/etc/systemd/system/serial-getty@.service.d"
665 mkdir
-p "$_getty_override"
666 echo -e "[Service]\nEnvironment=TERM=linux" > "$_getty_override/default-TERM.conf"
668 cat > "$initdir/etc/motd" << EOF
669 To adjust the terminal size use:
679 # install libnss_files for login
680 NSS_LIBS
=$
(LD_DEBUG
=files getent passwd
2>&1 >/dev
/null |
sed -n '/calling init: .*libnss_/ {s!^.* /!/!; p}')
681 dracut_install
$NSS_LIBS
685 inst
$ROOTLIBDIR/system
/dbus.socket
687 # Newer Fedora versions use dbus-broker by default. Let's install it is available.
688 if [ -f $ROOTLIBDIR/system
/dbus-broker.service
]; then
689 inst
$ROOTLIBDIR/system
/dbus-broker.service
690 inst_symlink
/etc
/systemd
/system
/dbus.service
691 inst
/usr
/bin
/dbus-broker
692 inst
/usr
/bin
/dbus-broker-launch
693 elif [ -f $ROOTLIBDIR/system
/dbus-daemon.service
]; then
694 # Fedora rawhide replaced dbus.service with dbus-daemon.service
695 inst
$ROOTLIBDIR/system
/dbus-daemon.service
697 inst_symlink
/etc
/systemd
/system
/dbus.service
699 inst
$ROOTLIBDIR/system
/dbus.service
703 /etc
/dbus-1
/usr
/share
/dbus-1
-xtype f \
704 |
while read file; do
711 if [[ "$LOOKS_LIKE_DEBIAN" ]] && type -p dpkg-architecture
&>/dev
/null
; then
712 find "/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security" -xtype f
714 find /lib
*/security
-xtype f
716 find /etc
/pam.d
/etc
/security
-xtype f
717 ) |
while read file; do
721 # pam_unix depends on unix_chkpwd.
722 # see http://www.linux-pam.org/Linux-PAM-html/sag-pam_unix.html
723 dracut_install
-o unix_chkpwd
725 [[ "$LOOKS_LIKE_DEBIAN" ]] &&
726 cp /etc
/pam.d
/systemd-user
$initdir/etc
/pam.d
/
728 # set empty root password for easy debugging
729 sed -i 's/^root:x:/root::/' $initdir/etc
/passwd
733 # The first three paths may be deprecated.
734 # It seems now the last two paths are used by many distributions.
736 /usr
/lib
/kbd
/keymaps
/include
/* \
737 /usr
/lib
/kbd
/keymaps
/i386
/include
/* \
738 /usr
/lib
/kbd
/keymaps
/i386
/qwerty
/us.
* \
739 /usr
/lib
/kbd
/keymaps
/legacy
/include
/* \
740 /usr
/lib
/kbd
/keymaps
/legacy
/i386
/qwerty
/us.
*; do
741 [[ -f $i ]] ||
continue
745 # When it takes any argument, then install more keymaps.
748 /usr
/lib
/kbd
/keymaps
/i386
/*/* \
749 /usr
/lib
/kbd
/keymaps
/legacy
/i386
/*/*; do
750 [[ -f $i ]] ||
continue
757 for i
in /usr
/share
/zoneinfo
/{,*/,*/*/}*; do
758 [[ -f $i ]] ||
continue
765 /usr
/lib
/kbd
/consolefonts
/eurlatgr
* \
766 /usr
/lib
/kbd
/consolefonts
/latarcyrheb-sun16
*; do
767 [[ -f $i ]] ||
continue
773 for _terminfodir
in /lib
/terminfo
/etc
/terminfo
/usr
/share
/terminfo
; do
774 [ -f ${_terminfodir}/l
/linux
] && break
776 dracut_install
-o ${_terminfodir}/l
/linux
780 cp $TEST_BASE_DIR/testsuite.target
$initdir/etc
/systemd
/system
/
781 cp $TEST_BASE_DIR/end.service
$initdir/etc
/systemd
/system
/
783 mkdir
-p $initdir/etc
/systemd
/system
/testsuite.target.wants
784 ln -fs $TEST_BASE_DIR/testsuite.service
$initdir/etc
/systemd
/system
/testsuite.target.wants
/testsuite.service
785 # Don't shutdown the machine after running the test when INTERACTIVE_DEBUG is set
786 [[ -z $INTERACTIVE_DEBUG ]] && ln -fs $TEST_BASE_DIR/end.service
$initdir/etc
/systemd
/system
/testsuite.target.wants
/end.service
788 # make the testsuite the default target
789 ln -fs testsuite.target
$initdir/etc
/systemd
/system
/default.target
792 setup_nspawn_root
() {
793 rm -fr $TESTDIR/nspawn-root
794 ddebug
"cp -ar $initdir $TESTDIR/nspawn-root"
795 cp -ar $initdir $TESTDIR/nspawn-root
796 # we don't mount in the nspawn root
797 rm -f $TESTDIR/nspawn-root
/etc
/fstab
798 if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then
799 cp -ar $TESTDIR/nspawn-root
$TESTDIR/unprivileged-nspawn-root
804 mkdir
-p $initdir/run
805 mkdir
-p $initdir/etc
/systemd
/system
806 mkdir
-p $initdir/var
/log
/journal
808 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
809 if [ -L "/$d" ]; then
816 ln -sfn /run
"$initdir/var/run"
817 ln -sfn /run
/lock
"$initdir/var/lock"
822 local _so_regex
='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
825 LC_ALL
=C ldd
"$_bin" 2>/dev
/null |
while read _line
; do
826 [[ $_line = 'not a dynamic executable' ]] && break
828 if [[ $_line =~
$_so_regex ]]; then
829 _file
=${BASH_REMATCH[1]}
830 [[ -e ${initdir}/$_file ]] && continue
831 inst_library
"$_file"
835 if [[ $_line =~ not\ found
]]; then
836 dfatal
"Missing a shared library required by $_bin."
837 dfatal
"Run \"ldd $_bin\" to find out what it is."
839 dfatal
"dracut cannot create an initrd."
846 [[ -e $STATEFILE ]] && .
$STATEFILE
847 if [[ ! -d "$TESTDIR" ]]; then
848 if [[ -z "$TESTDIR" ]]; then
849 TESTDIR
=$
(mktemp
--tmpdir=/var
/tmp
-d -t systemd-test.XXXXXX
)
854 echo "TESTDIR=\"$TESTDIR\"" > $STATEFILE
860 initdir
=$TESTDIR/root
864 ## @brief Converts numeric logging level to the first letter of level name.
866 # @param lvl Numeric logging level in range from 1 to 6.
867 # @retval 1 if @a lvl is out of range.
868 # @retval 0 if @a lvl is correct.
869 # @result Echoes first letter of level name.
882 ## @brief Internal helper function for _do_dlog()
884 # @param lvl Numeric logging level.
885 # @param msg Message.
886 # @retval 0 It's always returned, even if logging failed.
888 # @note This function is not supposed to be called manually. Please use
889 # dtrace(), ddebug(), or others instead which wrap this one.
891 # This function calls _do_dlog() either with parameter msg, or if
892 # none is given, it will read standard input and will use every line as
896 # dwarn "This is a warning"
897 # echo "This is a warning" | dwarn
898 LOG_LEVEL
=${LOG_LEVEL:-4}
901 [ -z "$LOG_LEVEL" ] && return 0
902 [ $1 -le $LOG_LEVEL ] ||
return 0
903 local lvl
="$1"; shift
904 local lvlc
=$
(_lvl2char
"$lvl") ||
return 0
906 if [ $# -ge 1 ]; then
910 echo "$lvlc: " "$line"
915 ## @brief Logs message at TRACE level (6)
917 # @param msg Message.
918 # @retval 0 It's always returned, even if logging failed.
922 [ -n "$debug" ] && set -x ||
:
925 ## @brief Logs message at DEBUG level (5)
927 # @param msg Message.
928 # @retval 0 It's always returned, even if logging failed.
932 # [ -n "$debug" ] && set -x || :
935 ## @brief Logs message at INFO level (4)
937 # @param msg Message.
938 # @retval 0 It's always returned, even if logging failed.
942 [ -n "$debug" ] && set -x ||
:
945 ## @brief Logs message at WARN level (3)
947 # @param msg Message.
948 # @retval 0 It's always returned, even if logging failed.
952 [ -n "$debug" ] && set -x ||
:
955 ## @brief Logs message at ERROR level (2)
957 # @param msg Message.
958 # @retval 0 It's always returned, even if logging failed.
962 # [ -n "$debug" ] && set -x || :
965 ## @brief Logs message at FATAL level (1)
967 # @param msg Message.
968 # @retval 0 It's always returned, even if logging failed.
972 [ -n "$debug" ] && set -x ||
:
976 # Generic substring function. If $2 is in $1, return 0.
977 strstr
() { [ "${1#*$2*}" != "$1" ]; }
979 # normalize_path <path>
980 # Prints the normalized path, where it removes any duplicated
981 # and trailing slashes.
983 # $ normalize_path ///test/test//
987 set -- "${1//+(\/)//}"
992 # convert_abs_rel <from> <to>
993 # Prints the relative path, when creating a symlink to <to> from <from>.
995 # $ convert_abs_rel /usr/bin/test /bin/test-2
997 # $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
999 local __current __absolute __abssize __cursize __newpath
1000 local -i __i __level
1002 set -- "$(normalize_path "$1")" "$(normalize_path "$2")"
1004 # corner case #1 - self looping link
1005 [[ "$1" == "$2" ]] && { echo "${1##*/}"; return; }
1007 # corner case #2 - own dir link
1008 [[ "${1%/*}" == "$2" ]] && { echo "."; return; }
1010 IFS
="/" __current
=($1)
1011 IFS
="/" __absolute
=($2)
1013 __abssize
=${#__absolute[@]}
1014 __cursize
=${#__current[@]}
1016 while [[ ${__absolute[__level]} == ${__current[__level]} ]]
1019 if (( __level
> __abssize || __level
> __cursize
))
1025 for ((__i
= __level
; __i
< __cursize-1
; __i
++))
1027 if ((__i
> __level
))
1029 __newpath
=$__newpath"/"
1031 __newpath
=$__newpath".."
1034 for ((__i
= __level
; __i
< __abssize
; __i
++))
1036 if [[ -n $__newpath ]]
1038 __newpath
=$__newpath"/"
1040 __newpath
=$__newpath${__absolute[__i]}
1047 # Install a directory, keeping symlinks as on the original system.
1048 # Example: if /lib points to /lib64 on the host, "inst_dir /lib/file"
1049 # will create ${initdir}/lib64, ${initdir}/lib64/file,
1050 # and a symlink ${initdir}/lib -> lib64.
1052 [[ -e ${initdir}/"$1" ]] && return 0 # already there
1054 local _dir
="$1" _part
="${1%/*}" _file
1055 while [[ "$_part" != "${_part%/*}" ]] && ! [[ -e "${initdir}/${_part}" ]]; do
1060 # iterate over parent directories
1061 for _file
in $_dir; do
1062 [[ -e "${initdir}/$_file" ]] && continue
1063 if [[ -L $_file ]]; then
1064 inst_symlink
"$_file"
1067 mkdir
-m 0755 -p "${initdir}/$_file" ||
return 1
1068 [[ -e "$_file" ]] && chmod --reference="$_file" "${initdir}/$_file"
1069 chmod u
+w
"${initdir}/$_file"
1074 # $1 = file to copy to ramdisk
1075 # $2 (optional) Name for the file on the ramdisk
1076 # Location of the image dir is assumed to be $initdir
1077 # We never overwrite the target if it exists.
1079 [[ -f "$1" ]] ||
return 1
1080 strstr
"$1" "/" ||
return 1
1082 local _src
=$1 target
="${2:-$1}"
1083 if ! [[ -d ${initdir}/$target ]]; then
1084 [[ -e ${initdir}/$target ]] && return 0
1085 [[ -L ${initdir}/$target ]] && return 0
1086 [[ -d "${initdir}/${target%/*}" ]] || inst_dir "${target%/*}"
1088 # install checksum files also
1089 if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then
1090 inst
"${_src%/*}/.${_src##*/}.hmac" "${target%/*}/.${target##*/}.hmac"
1092 ddebug
"Installing $_src"
1093 cp --sparse=always
-pfL "$_src" "${initdir}/$target"
1096 # find symlinks linked to given library file
1098 # Function searches for symlinks by stripping version numbers appended to
1099 # library filename, checks if it points to the same target and finally
1100 # prints the list of symlinks to stdout.
1103 # rev_lib_symlinks libfoo.so.8.1
1104 # output: libfoo.so.8 libfoo.so
1105 # (Only if libfoo.so.8 and libfoo.so exists on host system.)
1106 rev_lib_symlinks
() {
1107 [[ ! $1 ]] && return 0
1109 local fn
="$1" orig
="$(readlink -f "$1")" links
=''
1111 [[ ${fn} =~ .
*\.so\..
* ]] ||
return 1
1113 until [[ ${fn##*.} == so
]]; do
1115 [[ -L ${fn} && $(readlink -f "${fn}") == ${orig} ]] && links+=" ${fn}"
1121 # Same as above, but specialized to handle dynamic libraries.
1122 # It handles making symlinks according to how the original library
1125 local _src="$1" _dest=${2:-$1} _lib _reallib _symlink
1126 strstr "$1" "/" || return 1
1127 [[ -e $initdir/$_dest ]] && return 0
1128 if [[ -L $_src ]]; then
1129 # install checksum files also
1130 if [[ -e "${_src%/*}/.
${_src##*/}.hmac
" ]]; then
1131 inst "${_src%/*}/.${_src##*/}.hmac" "${_dest%/*}/.${_dest##*/}.hmac
"
1133 _reallib=$(readlink -f "$_src")
1134 inst_simple "$_reallib" "$_reallib"
1135 inst_dir "${_dest%/*}"
1136 [[ -d "${_dest%/*}" ]] && _dest=$(readlink -f "${_dest%/*}")/${_dest##*/}
1137 ln -sfn $
(convert_abs_rel
"${_dest}" "${_reallib}") "${initdir}/${_dest}"
1139 inst_simple
"$_src" "$_dest"
1142 # Create additional symlinks. See rev_symlinks description.
1143 for _symlink
in $
(rev_lib_symlinks
$_src) $
(rev_lib_symlinks
$_reallib); do
1144 [[ -e $initdir/$_symlink ]] ||
{
1145 ddebug
"Creating extra symlink: $_symlink"
1146 inst_symlink
$_symlink
1151 # find a binary. If we were not passed the full path directly,
1152 # search in the usual places to find the binary.
1154 if [[ -z ${1##/*} ]]; then
1155 if [[ -x $1 ]] ||
{ strstr
"$1" ".so" && ldd
$1 &>/dev
/null
; }; then
1164 # Same as above, but specialized to install binary executables.
1165 # Install binary executable, and all shared library dependencies, if any.
1168 _bin
=$
(find_binary
"$1") ||
return 1
1170 [[ -e $initdir/$_target ]] && return 0
1171 [[ -L $_bin ]] && inst_symlink
$_bin $_target && return 0
1173 local _so_regex
='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
1175 LC_ALL
=C ldd
"$_bin" 2>/dev
/null |
while read _line
; do
1176 [[ $_line = 'not a dynamic executable' ]] && break
1178 if [[ $_line =~
$_so_regex ]]; then
1179 _file
=${BASH_REMATCH[1]}
1180 [[ -e ${initdir}/$_file ]] && continue
1181 inst_library
"$_file"
1185 if [[ $_line =~ not\ found
]]; then
1186 dfatal
"Missing a shared library required by $_bin."
1187 dfatal
"Run \"ldd $_bin\" to find out what it is."
1189 dfatal
"dracut cannot create an initrd."
1193 inst_simple
"$_bin" "$_target"
1196 # same as above, except for shell scripts.
1197 # If your shell script does not start with shebang, it is not a shell script.
1200 _bin
=$
(find_binary
"$1") ||
return 1
1202 local _line _shebang_regex
1203 read -r -n 80 _line
<"$_bin"
1204 # If debug is set, clean unprintable chars to prevent messing up the term
1205 [[ $debug ]] && _line
=$
(echo -n "$_line" |
tr -c -d '[:print:][:space:]')
1206 _shebang_regex
='(#! *)(/[^ ]+).*'
1207 [[ $_line =~
$_shebang_regex ]] ||
return 1
1208 inst
"${BASH_REMATCH[2]}" && inst_simple
"$_bin" "$@"
1211 # same as above, but specialized for symlinks
1213 local _src
=$1 _target
=${2:-$1} _realsrc
1214 strstr
"$1" "/" ||
return 1
1215 [[ -L $1 ]] ||
return 1
1216 [[ -L $initdir/$_target ]] && return 0
1217 _realsrc
=$
(readlink
-f "$_src")
1218 if ! [[ -e $initdir/$_realsrc ]]; then
1219 if [[ -d $_realsrc ]]; then
1220 inst_dir
"$_realsrc"
1225 [[ ! -e $initdir/${_target%/*} ]] && inst_dir
"${_target%/*}"
1226 [[ -d ${_target%/*} ]] && _target=$(readlink -f ${_target%/*})/${_target##*/}
1227 ln -sfn $
(convert_abs_rel
"${_target}" "${_realsrc}") "$initdir/$_target"
1230 # attempt to install any programs specified in a udev rule
1231 inst_rule_programs
() {
1234 if grep -qE 'PROGRAM==?"[^ "]+' "$1"; then
1235 for _prog
in $
(grep -E 'PROGRAM==?"[^ "]+' "$1" |
sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/'); do
1236 if [ -x /lib
/udev
/$_prog ]; then
1237 _bin
=/lib
/udev
/$_prog
1239 _bin
=$
(find_binary
"$_prog") ||
{
1240 dinfo
"Skipping program $_prog using in udev rule $(basename $1) as it cannot be found"
1245 #dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)"
1246 dracut_install
"$_bin"
1251 # udev rules always get installed in the same place, so
1252 # create a function to install them to make life simpler.
1254 local _target
=/etc
/udev
/rules.d _rule _found
1256 inst_dir
"/lib/udev/rules.d"
1258 for _rule
in "$@"; do
1259 if [ "${rule#/}" = "$rule" ]; then
1260 for r
in /lib
/udev
/rules.d
/etc
/udev
/rules.d
; do
1261 if [[ -f $r/$_rule ]]; then
1263 inst_simple
"$_found"
1264 inst_rule_programs
"$_found"
1268 for r
in '' .
/ $dracutbasedir/rules.d
/; do
1269 if [[ -f ${r}$_rule ]]; then
1271 inst_simple
"$_found" "$_target/${_found##*/}"
1272 inst_rule_programs
"$_found"
1275 [[ $_found ]] || dinfo
"Skipping udev rule: $_rule"
1280 # general purpose installation function
1281 # Same args as above.
1287 2) [[ ! $initdir && -d $2 ]] && export initdir
=$2
1288 [[ $initdir = $2 ]] && set $1;;
1289 3) [[ -z $initdir ]] && export initdir
=$2
1291 *) dfatal
"inst only takes 1 or 2 or 3 arguments"
1294 for _x
in inst_symlink inst_script inst_binary inst_simple
; do
1295 $_x "$@" && return 0
1300 # install any of listed files
1302 # If first argument is '-d' and second some destination path, first accessible
1303 # source is installed into this path, otherwise it will installed in the same
1304 # path as source. If none of listed files was installed, function return 1.
1305 # On first successful installation it returns with 0 status.
1309 # inst_any -d /bin/foo /bin/bar /bin/baz
1311 # Lets assume that /bin/baz exists, so it will be installed as /bin/foo in
1316 [[ $1 = '-d' ]] && to
="$2" && shift 2
1319 if [[ -e $f ]]; then
1320 [[ $to ]] && inst
"$f" "$to" && return 0
1321 inst
"$f" && return 0
1328 # dracut_install [-o ] <file> [<file> ... ]
1329 # Install <file> to the initramfs image
1330 # -o optionally install the <file> and don't fail, if it is not there
1333 if [[ $1 = '-o' ]]; then
1337 while (($# > 0)); do
1338 if ! inst
"$1" ; then
1339 if [[ $_optional = yes ]]; then
1340 dinfo
"Skipping program $1 as it cannot be found and is" \
1341 "flagged to be optional"
1343 dfatal
"Failed to install $1"
1351 # Install a single kernel module along with any firmware it may require.
1352 # $1 = full path to kernel module to install
1353 install_kmod_with_fw
() {
1354 # no need to go further if the module is already installed
1356 [[ -e "${initdir}/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" ]] \
1359 [[ -e "$initdir/.kernelmodseen/${1##*/}" ]] && return 0
1361 if [[ $omit_drivers ]]; then
1362 local _kmod
=${1##*/}
1365 if [[ "$_kmod" =~
$omit_drivers ]]; then
1366 dinfo
"Omitting driver $_kmod"
1369 if [[ "${1##*/lib/modules/$KERNEL_VER/}" =~
$omit_drivers ]]; then
1370 dinfo
"Omitting driver $_kmod"
1375 [ -d "$initdir/.kernelmodseen" ] && \
1376 > "$initdir/.kernelmodseen/${1##*/}"
1378 inst_simple
"$1" "/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" \
1381 local _modname
=${1##*/} _fwdir _found _fw
1382 _modname
=${_modname%.ko*}
1383 for _fw
in $
(modinfo
-k $KERNEL_VER -F firmware
$1 2>/dev
/null
); do
1385 for _fwdir
in $fw_dir; do
1386 if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then
1387 inst_simple
"$_fwdir/$_fw" "/lib/firmware/$_fw"
1391 if [[ $_found != yes ]]; then
1392 if ! grep -qe "\<${_modname//-/_}\>" /proc
/modules
; then
1393 dinfo
"Possible missing firmware \"${_fw}\" for kernel module" \
1394 "\"${_modname}.ko\""
1396 dwarn
"Possible missing firmware \"${_fw}\" for kernel module" \
1397 "\"${_modname}.ko\""
1404 # Do something with all the dependencies of a kernel module.
1405 # Note that kernel modules depend on themselves using the technique we use
1406 # $1 = function to call for each dependency we find
1407 # It will be passed the full path to the found kernel module
1408 # $2 = module to get dependencies for
1409 # rest of args = arguments to modprobe
1410 # _fderr specifies FD passed from surrounding scope
1411 for_each_kmod_dep
() {
1412 local _func
=$1 _kmod
=$2 _cmd _modpath _options _found
=0
1414 modprobe
"$@" --ignore-install --show-depends $_kmod 2>&${_fderr} |
(
1415 while read _cmd _modpath _options
; do
1416 [[ $_cmd = insmod
]] ||
continue
1417 $_func ${_modpath} ||
exit $?
1420 [[ $_found -eq 0 ]] && exit 1
1425 # filter kernel modules to install certain modules that meet specific
1427 # $1 = search only in subdirectory of /kernel/$1
1428 # $2 = function to call with module name to filter.
1429 # This function will be passed the full path to the module to test.
1430 # The behavior of this function can vary depending on whether $hostonly is set.
1431 # If it is, we will only look at modules that are already in memory.
1432 # If it is not, we will look at all kernel modules
1433 # This function returns the full filenames of modules that match $1
1434 filter_kernel_modules_by_path
() (
1435 local _modname _filtercmd
1436 if ! [[ $hostonly ]]; then
1437 _filtercmd
='find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra"'
1438 _filtercmd
+=' "$KERNEL_MODS/weak-updates" -name "*.ko" -o -name "*.ko.gz"'
1439 _filtercmd
+=' -o -name "*.ko.xz"'
1440 _filtercmd
+=' 2>/dev/null'
1442 _filtercmd
='cut -d " " -f 1 </proc/modules|xargs modinfo -F filename '
1443 _filtercmd
+='-k $KERNEL_VER 2>/dev/null'
1445 for _modname
in $
(eval $_filtercmd); do
1447 *.ko
) "$2" "$_modname" && echo "$_modname";;
1448 *.ko.gz
) gzip -dc "$_modname" > $initdir/$$.ko
1449 $2 $initdir/$$.ko
&& echo "$_modname"
1450 rm -f $initdir/$$.ko
1452 *.ko.xz
) xz
-dc "$_modname" > $initdir/$$.ko
1453 $2 $initdir/$$.ko
&& echo "$_modname"
1454 rm -f $initdir/$$.ko
1459 find_kernel_modules_by_path
() (
1460 if ! [[ $hostonly ]]; then
1461 find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra" "$KERNEL_MODS/weak-updates" \
1462 -name "*.ko" -o -name "*.ko.gz" -o -name "*.ko.xz" 2>/dev
/null
1464 cut
-d " " -f 1 </proc
/modules \
1465 |
xargs modinfo
-F filename
-k $KERNEL_VER 2>/dev
/null
1469 filter_kernel_modules
() {
1470 filter_kernel_modules_by_path drivers
"$1"
1473 find_kernel_modules
() {
1474 find_kernel_modules_by_path drivers
1477 # instmods [-c] <kernel module> [<kernel module> ... ]
1478 # instmods [-c] <kernel subsystem>
1479 # install kernel modules along with all their dependencies.
1480 # <kernel subsystem> can be e.g. "=block" or "=drivers/usb/storage"
1482 [[ $no_kernel = yes ]] && return
1483 # called [sub]functions inherit _fderr
1486 if [[ $1 = '-c' ]]; then
1491 function inst1mod
() {
1492 local _ret
=0 _mod
="$1"
1495 if [ -f $KERNEL_MODS/modules.
${_mod#=} ]; then
1496 ( [[ "$_mpargs" ]] && echo $_mpargs
1497 cat "${KERNEL_MODS}/modules.${_mod#=}" ) \
1500 ( [[ "$_mpargs" ]] && echo $_mpargs
1501 find "$KERNEL_MODS" -path "*/${_mod#=}/*" -printf '%f\n' ) \
1505 --*) _mpargs
+=" $_mod" ;;
1506 i2o_scsi
) return ;; # Do not load this diagnostic-only module
1509 # if we are already installed, skip this module and go on
1511 [[ -f "$initdir/.kernelmodseen/${_mod%.ko}.ko" ]] && return
1513 if [[ $omit_drivers ]] && [[ "$1" =~
$omit_drivers ]]; then
1514 dinfo
"Omitting driver ${_mod##$KERNEL_MODS}"
1517 # If we are building a host-specific initramfs and this
1518 # module is not already loaded, move on to the next one.
1519 [[ $hostonly ]] && ! grep -qe "\<${_mod//-/_}\>" /proc
/modules \
1520 && ! echo $add_drivers |
grep -qe "\<${_mod}\>" \
1523 # We use '-d' option in modprobe only if modules prefix path
1524 # differs from default '/'. This allows us to use Dracut with
1525 # old version of modprobe which doesn't have '-d' option.
1526 local _moddirname
=${KERNEL_MODS%%/lib/modules/*}
1527 [[ -n ${_moddirname} ]] && _moddirname
="-d ${_moddirname}/"
1529 # ok, load the module, all its dependencies, and any firmware
1531 for_each_kmod_dep install_kmod_with_fw
$_mod \
1532 --set-version $KERNEL_VER ${_moddirname} $_mpargs
1539 function instmods_1
() {
1541 if (($# == 0)); then # filenames from stdin
1543 inst1mod
"${_mod%.ko*}" ||
{
1544 if [ "$_check" = "yes" ]; then
1545 dfatal
"Failed to install $_mod"
1551 while (($# > 0)); do # filenames as arguments
1552 inst1mod
${1%.ko*} ||
{
1553 if [ "$_check" = "yes" ]; then
1554 dfatal
"Failed to install $1"
1563 local _ret _filter_not_found
='FATAL: Module .* not found.'
1565 # Capture all stderr from modprobe to _fderr. We could use {var}>...
1566 # redirections, but that would make dracut require bash4 at least.
1567 eval "( instmods_1 \"\$@\" ) ${_fderr}>&1" \
1568 |
while read line
; do [[ "$line" =~
$_filter_not_found ]] && echo $line ||
echo $line >&2 ;done | derror
1574 # inst_libdir_file [-n <pattern>] <file> [<file>...]
1575 # Install a <file> located on a lib directory to the initramfs image
1576 # -n <pattern> install non-matching files
1577 inst_libdir_file
() {
1578 if [[ "$1" == "-n" ]]; then
1581 for _dir
in $libdirs; do
1583 for _f
in "$_dir"/$_i; do
1584 [[ "$_i" =~
$_pattern ]] ||
continue
1585 [[ -e "$_i" ]] && dracut_install
"$_i"
1590 for _dir
in $libdirs; do
1592 for _f
in "$_dir"/$_i; do
1593 [[ -e "$_f" ]] && dracut_install
"$_f"
1601 ln -fs ..
/usr
/bin
/systemctl
$initdir/bin
/
1602 ln -fs ..
/usr
/lib
/systemd
$initdir/lib
/
1603 inst_simple
"/usr/lib/systemd/system/haveged.service"
1606 # can be overridden in specific test
1608 umount
$TESTDIR/root
2>/dev
/null || true
1609 [[ $LOOPDEV ]] && losetup
-d $LOOPDEV || true
1614 if [ -z "$TEST_NO_QEMU" ]; then
1616 check_result_qemu ||
return 1
1618 dwarn
"can't run QEMU, skipping"
1621 if [ -z "$TEST_NO_NSPAWN" ]; then
1622 if run_nspawn
"nspawn-root"; then
1623 check_result_nspawn
"nspawn-root" ||
return 1
1625 dwarn
"can't run systemd-nspawn, skipping"
1628 if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then
1629 if NSPAWN_ARGUMENTS
="-U --private-network $NSPAWN_ARGUMENTS" run_nspawn
"unprivileged-nspawn-root"; then
1630 check_result_nspawn
"unprivileged-nspawn-root" ||
return 1
1632 dwarn
"can't run systemd-nspawn, skipping"
1640 if [[ $UID != "0" ]]; then
1641 echo "TEST: $TEST_DESCRIPTION [SKIPPED]: not root" >&2
1646 [[ $libdir ]] ||
for libdir
in /lib64
/lib
; do
1647 [[ -d $libdir ]] && libdirs
+=" $libdir" && break
1650 [[ $usrlibdir ]] ||
for usrlibdir
in /usr
/lib64
/usr
/lib
; do
1651 [[ -d $usrlibdir ]] && libdirs
+=" $usrlibdir" && break
1654 mkdir
-p "$STATEDIR"
1659 while (($# > 0)); do
1662 echo "TEST RUN: $TEST_DESCRIPTION"
1665 if (( $ret == 0 )); then
1666 echo "TEST RUN: $TEST_DESCRIPTION [OK]"
1668 echo "TEST RUN: $TEST_DESCRIPTION [FAILED]"
1672 echo "TEST SETUP: $TEST_DESCRIPTION"
1676 echo "TEST CLEANUP: $TEST_DESCRIPTION"
1683 echo -n "TEST: $TEST_DESCRIPTION ";
1685 test_setup
&& test_run
1691 ) </dev
/null
>"$TESTLOG" 2>&1 || ret
=$?
1692 if [ $ret -eq 0 ]; then