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
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\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 # The 'mount' utility doesn't behave well under libasan, causing unexpected
390 # fails during boot and subsequent test results check:
391 # bash-5.0# mount -o remount,rw -v /
392 # mount: /dev/sda1 mounted on /.
395 # Let's workaround this by clearing the previously set LD_PRELOAD env variable,
396 # so the libasan library is not loaded for this particular service
397 REMOUNTFS_CONF_DIR=/etc/systemd/system/systemd-remount-fs.service.d
398 mkdir -p "\$REMOUNTFS_CONF_DIR"
399 printf "[Service]\nUnsetEnvironment=LD_PRELOAD\n" >"\$REMOUNTFS_CONF_DIR/env.conf"
401 export ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS
402 exec $ROOTLIBDIR/systemd "\$@"
405 chmod 0755 $_asan_wrapper
408 create_strace_wrapper
() {
409 local _strace_wrapper
=$initdir/$ROOTLIBDIR/systemd-under-strace
410 ddebug
"Create $_strace_wrapper"
411 cat >$_strace_wrapper <<EOF
414 exec strace -D -o /strace.out $ROOTLIBDIR/systemd "\$@"
416 chmod 0755 $_strace_wrapper
420 dracut_install
/sbin
/fsck
*
421 dracut_install
-o /bin
/fsck
*
423 # fskc.reiserfs calls reiserfsck. so, install it
424 dracut_install
-o reiserfsck
428 instmods dm_crypt
=crypto
429 type -P dmeventd
>/dev
/null
&& dracut_install dmeventd
430 inst_libdir_file
"libdevmapper-event.so*"
431 if [[ "$LOOKS_LIKE_DEBIAN" ]]; then
432 # dmsetup installs 55-dm and 60-persistent-storage-dm on Debian/Ubuntu
433 # and since buster/bionic 95-dm-notify.rules
434 # see https://gitlab.com/debian-lvm/lvm2/blob/master/debian/patches/udev.patch
435 inst_rules
55-dm.rules
60-persistent-storage-dm.rules
95-dm-notify.rules
437 inst_rules
10-dm.rules
13-dm-disk.rules
95-dm-notify.rules
442 # install compiled files
443 local _ninja_bin
=$
(type -P ninja ||
type -P ninja-build
)
444 if [[ -z "$_ninja_bin" ]]; then
445 dfatal
"ninja was not found"
448 (set -x; DESTDIR
=$initdir "$_ninja_bin" -C $BUILD_DIR install)
449 # remove unneeded documentation
450 rm -fr $initdir/usr
/share
/{man
,doc
}
451 # we strip binaries since debug symbols increase binaries size a lot
452 # and it could fill the available space
455 [[ "$LOOKS_LIKE_SUSE" ]] && setup_suse
457 # enable debug logging in PID1
458 echo LogLevel
=debug
>> $initdir/etc
/systemd
/system.conf
463 objdump
-p "$_bin" 2>/dev
/null |
awk "/R(UN)?PATH/ { print \"$initdir\" \$2 }" |
paste -sd :
466 install_missing_libraries
() {
467 # install possible missing libraries
468 for i
in $initdir{,/usr
}/{sbin
,bin
}/* $initdir{,/usr
}/lib
/systemd
/{,tests
/{,manual
/,unsafe
/}}*; do
469 LD_LIBRARY_PATH
=$
(get_ldpath
$i) inst_libs
$i
473 create_empty_image
() {
475 if [[ "$STRIP_BINARIES" = "no" ]]; then
478 rm -f "$TESTDIR/rootdisk.img"
479 # Create the blank file to use as a root filesystem
480 dd if=/dev
/null of
="$TESTDIR/rootdisk.img" bs
=1M seek
="$_size"
481 LOOPDEV
=$
(losetup
--show -P -f $TESTDIR/rootdisk.img
)
482 [ -b "$LOOPDEV" ] ||
return 1
483 echo "LOOPDEV=$LOOPDEV" >> $STATEFILE
484 sfdisk
"$LOOPDEV" <<EOF
491 local _label
="-L systemd"
492 # mkfs.reiserfs doesn't know -L. so, use --label instead
493 [[ "$FSTYPE" == "reiserfs" ]] && _label
="--label systemd"
494 if ! mkfs
-t "${FSTYPE}" ${_label} "${LOOPDEV}p1" -q; then
495 dfatal
"Failed to mkfs -t ${FSTYPE}"
500 check_asan_reports
() {
504 if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
506 if [[ -e "$root/systemd.asan.log.1" ]]; then
507 cat "$root/systemd.asan.log.1"
511 journald_report
=$
(find "$root" -name "systemd-journald.asan.log*" -exec cat {} \
;)
512 if [[ ! -z "$journald_report" ]]; then
513 printf "%s" "$journald_report"
518 "$BUILD_DIR/journalctl" -D "$root/var/log/journal" | perl
-alne '
520 %services_to_ignore = (
521 "dbus-daemon" => undef,
524 print $2 if /\s(\S*)\[(\d+)\]:\s*SUMMARY:\s+\w+Sanitizer/ && !exists $services_to_ignore{$1}'
526 if [[ ! -z "$pids" ]]; then
529 "$BUILD_DIR/journalctl" -D "$root/var/log/journal" _PID
=$pid --no-pager
537 check_result_nspawn
() {
539 local journald_report
=""
541 [[ -e $TESTDIR/$1/testok
]] && ret
=0
542 [[ -f $TESTDIR/$1/failed
]] && cp -a $TESTDIR/$1/failed
$TESTDIR
543 cp -a $TESTDIR/$1/var
/log
/journal
$TESTDIR
544 [[ -f $TESTDIR/failed
]] && cat $TESTDIR/failed
545 ls -l $TESTDIR/journal
/*/*.journal
546 test -s $TESTDIR/failed
&& ret
=$
(($ret+1))
547 [ -n "$TIMED_OUT" ] && ret
=$
(($ret+1))
548 check_asan_reports
"$TESTDIR/$1" || ret
=$
(($ret+1))
552 # can be overridden in specific test
553 check_result_qemu
() {
555 mkdir
-p $TESTDIR/root
556 mount
${LOOPDEV}p1
$TESTDIR/root
557 [[ -e $TESTDIR/root
/testok
]] && ret
=0
558 [[ -f $TESTDIR/root
/failed
]] && cp -a $TESTDIR/root
/failed
$TESTDIR
559 cp -a $TESTDIR/root
/var
/log
/journal
$TESTDIR
560 check_asan_reports
"$TESTDIR/root" || ret
=$
(($ret+1))
562 [[ -f $TESTDIR/failed
]] && cat $TESTDIR/failed
563 ls -l $TESTDIR/journal
/*/*.journal
564 test -s $TESTDIR/failed
&& ret
=$
(($ret+1))
565 [ -n "$TIMED_OUT" ] && ret
=$
(($ret+1))
570 if [[ "$STRIP_BINARIES" = "no" ]]; then
571 ddebug
"Don't strip binaries"
574 ddebug
"Strip binaries"
575 find "$initdir" -executable -not -path '*/lib/modules/*.ko' -type f | \
576 xargs strip
--strip-unneeded |
& \
577 grep -v 'file format not recognized' | \
582 mkdir
-p $initdir/etc
/rc.d
583 cat >$initdir/etc
/rc.d
/rc.
local <<EOF
587 chmod 0755 $initdir/etc
/rc.d
/rc.
local
591 ddebug
"install any Execs from the service files"
593 export PKG_CONFIG_PATH
=$BUILD_DIR/src
/core
/
594 systemdsystemunitdir
=$
(pkg-config
--variable=systemdsystemunitdir systemd
)
595 systemduserunitdir
=$
(pkg-config
--variable=systemduserunitdir systemd
)
596 sed -r -n 's|^Exec[a-zA-Z]*=[@+!-]*([^ ]+).*|\1|gp' $initdir/{$systemdsystemunitdir,$systemduserunitdir}/*.service \
597 |
sort -u |
while read i
; do
598 # some {rc,halt}.local scripts and programs are okay to not exist, the rest should
599 # also, plymouth is pulled in by rescue.service, but even there the exit code
600 # is ignored; as it's not present on some distros, don't fail if it doesn't exist
601 inst
$i ||
[ "${i%.local}" != "$i" ] ||
[ "${i%systemd-update-done}" != "$i" ] ||
[ "/bin/plymouth" == "$i" ]
606 generate_module_dependencies
() {
607 if [[ -d $initdir/lib
/modules
/$KERNEL_VER ]] && \
608 ! depmod
-a -b "$initdir" $KERNEL_VER; then
609 dfatal
"\"depmod -a $KERNEL_VER\" failed."
614 install_depmod_files
() {
615 inst
/lib
/modules
/$KERNEL_VER/modules.order
616 inst
/lib
/modules
/$KERNEL_VER/modules.
builtin
620 # install plymouth, if found... else remove plymouth service files
621 # if [ -x /usr/libexec/plymouth/plymouth-populate-initrd ]; then
622 # PLYMOUTH_POPULATE_SOURCE_FUNCTIONS="$TEST_BASE_DIR/test-functions" \
623 # /usr/libexec/plymouth/plymouth-populate-initrd -t $initdir
624 # dracut_install plymouth plymouthd
626 rm -f $initdir/{usr
/lib
,etc
}/systemd
/system
/plymouth
* $initdir/{usr
/lib
,etc
}/systemd
/system
/*/plymouth
*
630 install_ld_so_conf
() {
631 cp -a /etc
/ld.so.conf
* $initdir/etc
632 ldconfig
-r "$initdir"
635 install_config_files
() {
636 inst
/etc
/sysconfig
/init || true
642 inst
/etc
/nsswitch.conf
643 inst
/etc
/pam.conf || true
644 inst
/etc
/securetty || true
647 # we want an empty environment
648 > $initdir/etc
/environment
649 > $initdir/etc
/machine-id
651 echo systemd-testsuite
> $initdir/etc
/hostname
653 if [[ "$LOOKS_LIKE_SUSE" ]]; then
654 ROOTMOUNT
="/dev/sda1 / ${FSTYPE} rw 0 1"
656 ROOTMOUNT
="LABEL=systemd / ${FSTYPE} rw 0 1"
659 cat >$initdir/etc
/fstab
<<EOF
664 install_basic_tools
() {
665 [[ $BASICTOOLS ]] && dracut_install
$BASICTOOLS
666 dracut_install
-o sushell
667 # in Debian ldconfig is just a shell script wrapper around ldconfig.real
668 dracut_install
-o ldconfig.real
671 install_debug_tools
() {
672 [[ $DEBUGTOOLS ]] && dracut_install
$DEBUGTOOLS
674 if [[ $INTERACTIVE_DEBUG ]]; then
675 # Set default TERM from vt220 to linux, so at least basic key shortcuts work
676 local _getty_override
="$initdir/etc/systemd/system/serial-getty@.service.d"
677 mkdir
-p "$_getty_override"
678 echo -e "[Service]\nEnvironment=TERM=linux" > "$_getty_override/default-TERM.conf"
680 cat > "$initdir/etc/motd" << EOF
681 To adjust the terminal size use:
691 # install libnss_files for login
692 NSS_LIBS
=$
(LD_DEBUG
=files getent passwd
2>&1 >/dev
/null |
sed -n '/calling init: .*libnss_/ {s!^.* /!/!; p}')
693 dracut_install
$NSS_LIBS
697 inst
$ROOTLIBDIR/system
/dbus.socket
699 # Fedora rawhide replaced dbus.service with dbus-daemon.service
700 if [ -f $ROOTLIBDIR/system
/dbus-daemon.service
]; then
701 inst
$ROOTLIBDIR/system
/dbus-daemon.service
703 inst_symlink
/etc
/systemd
/system
/dbus.service
705 inst
$ROOTLIBDIR/system
/dbus.service
707 # Newer Fedora versions use dbus-broker by default. Let's install it is available.
708 [ -f /usr
/bin
/dbus-broker
] && inst
/usr
/bin
/dbus-broker
709 [ -f /usr
/bin
/dbus-broker-launch
] && inst
/usr
/bin
/dbus-broker-launch
712 /etc
/dbus-1
/usr
/share
/dbus-1
-xtype f \
713 |
while read file; do
720 if [[ "$LOOKS_LIKE_DEBIAN" ]] && type -p dpkg-architecture
&>/dev
/null
; then
721 find "/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security" -xtype f
723 find /lib
*/security
-xtype f
725 find /etc
/pam.d
/etc
/security
-xtype f
726 ) |
while read file; do
730 # pam_unix depends on unix_chkpwd.
731 # see http://www.linux-pam.org/Linux-PAM-html/sag-pam_unix.html
732 dracut_install
-o unix_chkpwd
734 [[ "$LOOKS_LIKE_DEBIAN" ]] &&
735 cp /etc
/pam.d
/systemd-user
$initdir/etc
/pam.d
/
737 # set empty root password for easy debugging
738 sed -i 's/^root:x:/root::/' $initdir/etc
/passwd
742 # The first three paths may be deprecated.
743 # It seems now the last two paths are used by many distributions.
745 /usr
/lib
/kbd
/keymaps
/include
/* \
746 /usr
/lib
/kbd
/keymaps
/i386
/include
/* \
747 /usr
/lib
/kbd
/keymaps
/i386
/qwerty
/us.
* \
748 /usr
/lib
/kbd
/keymaps
/legacy
/include
/* \
749 /usr
/lib
/kbd
/keymaps
/legacy
/i386
/qwerty
/us.
*; do
750 [[ -f $i ]] ||
continue
754 # When it takes any argument, then install more keymaps.
757 /usr
/lib
/kbd
/keymaps
/i386
/*/* \
758 /usr
/lib
/kbd
/keymaps
/legacy
/i386
/*/*; do
759 [[ -f $i ]] ||
continue
766 for i
in /usr
/share
/zoneinfo
/{,*/,*/*/}*; do
767 [[ -f $i ]] ||
continue
774 /usr
/lib
/kbd
/consolefonts
/eurlatgr
* \
775 /usr
/lib
/kbd
/consolefonts
/latarcyrheb-sun16
*; do
776 [[ -f $i ]] ||
continue
782 for _terminfodir
in /lib
/terminfo
/etc
/terminfo
/usr
/share
/terminfo
; do
783 [ -f ${_terminfodir}/l
/linux
] && break
785 dracut_install
-o ${_terminfodir}/l
/linux
789 cp $TEST_BASE_DIR/testsuite.target
$initdir/etc
/systemd
/system
/
790 cp $TEST_BASE_DIR/end.service
$initdir/etc
/systemd
/system
/
792 mkdir
-p $initdir/etc
/systemd
/system
/testsuite.target.wants
793 ln -fs $TEST_BASE_DIR/testsuite.service
$initdir/etc
/systemd
/system
/testsuite.target.wants
/testsuite.service
794 # Don't shutdown the machine after running the test when INTERACTIVE_DEBUG is set
795 [[ -z $INTERACTIVE_DEBUG ]] && ln -fs $TEST_BASE_DIR/end.service
$initdir/etc
/systemd
/system
/testsuite.target.wants
/end.service
797 # make the testsuite the default target
798 ln -fs testsuite.target
$initdir/etc
/systemd
/system
/default.target
801 setup_nspawn_root
() {
802 rm -fr $TESTDIR/nspawn-root
803 ddebug
"cp -ar $initdir $TESTDIR/nspawn-root"
804 cp -ar $initdir $TESTDIR/nspawn-root
805 # we don't mount in the nspawn root
806 rm -f $TESTDIR/nspawn-root
/etc
/fstab
807 if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then
808 cp -ar $TESTDIR/nspawn-root
$TESTDIR/unprivileged-nspawn-root
813 mkdir
-p $initdir/run
814 mkdir
-p $initdir/etc
/systemd
/system
815 mkdir
-p $initdir/var
/log
/journal
817 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
818 if [ -L "/$d" ]; then
825 ln -sfn /run
"$initdir/var/run"
826 ln -sfn /run
/lock
"$initdir/var/lock"
831 local _so_regex
='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
834 LC_ALL
=C ldd
"$_bin" 2>/dev
/null |
while read _line
; do
835 [[ $_line = 'not a dynamic executable' ]] && break
837 if [[ $_line =~
$_so_regex ]]; then
838 _file
=${BASH_REMATCH[1]}
839 [[ -e ${initdir}/$_file ]] && continue
840 inst_library
"$_file"
844 if [[ $_line =~ not\ found
]]; then
845 dfatal
"Missing a shared library required by $_bin."
846 dfatal
"Run \"ldd $_bin\" to find out what it is."
848 dfatal
"dracut cannot create an initrd."
855 [[ -e $STATEFILE ]] && .
$STATEFILE
856 if [[ ! -d "$TESTDIR" ]]; then
857 if [[ -z "$TESTDIR" ]]; then
858 TESTDIR
=$
(mktemp
--tmpdir=/var
/tmp
-d -t systemd-test.XXXXXX
)
863 echo "TESTDIR=\"$TESTDIR\"" > $STATEFILE
869 initdir
=$TESTDIR/root
873 ## @brief Converts numeric logging level to the first letter of level name.
875 # @param lvl Numeric logging level in range from 1 to 6.
876 # @retval 1 if @a lvl is out of range.
877 # @retval 0 if @a lvl is correct.
878 # @result Echoes first letter of level name.
891 ## @brief Internal helper function for _do_dlog()
893 # @param lvl Numeric logging level.
894 # @param msg Message.
895 # @retval 0 It's always returned, even if logging failed.
897 # @note This function is not supposed to be called manually. Please use
898 # dtrace(), ddebug(), or others instead which wrap this one.
900 # This function calls _do_dlog() either with parameter msg, or if
901 # none is given, it will read standard input and will use every line as
905 # dwarn "This is a warning"
906 # echo "This is a warning" | dwarn
907 LOG_LEVEL
=${LOG_LEVEL:-4}
910 [ -z "$LOG_LEVEL" ] && return 0
911 [ $1 -le $LOG_LEVEL ] ||
return 0
912 local lvl
="$1"; shift
913 local lvlc
=$
(_lvl2char
"$lvl") ||
return 0
915 if [ $# -ge 1 ]; then
919 echo "$lvlc: " "$line"
924 ## @brief Logs message at TRACE level (6)
926 # @param msg Message.
927 # @retval 0 It's always returned, even if logging failed.
931 [ -n "$debug" ] && set -x ||
:
934 ## @brief Logs message at DEBUG level (5)
936 # @param msg Message.
937 # @retval 0 It's always returned, even if logging failed.
941 # [ -n "$debug" ] && set -x || :
944 ## @brief Logs message at INFO level (4)
946 # @param msg Message.
947 # @retval 0 It's always returned, even if logging failed.
951 [ -n "$debug" ] && set -x ||
:
954 ## @brief Logs message at WARN level (3)
956 # @param msg Message.
957 # @retval 0 It's always returned, even if logging failed.
961 [ -n "$debug" ] && set -x ||
:
964 ## @brief Logs message at ERROR level (2)
966 # @param msg Message.
967 # @retval 0 It's always returned, even if logging failed.
971 # [ -n "$debug" ] && set -x || :
974 ## @brief Logs message at FATAL level (1)
976 # @param msg Message.
977 # @retval 0 It's always returned, even if logging failed.
981 [ -n "$debug" ] && set -x ||
:
985 # Generic substring function. If $2 is in $1, return 0.
986 strstr
() { [ "${1#*$2*}" != "$1" ]; }
988 # normalize_path <path>
989 # Prints the normalized path, where it removes any duplicated
990 # and trailing slashes.
992 # $ normalize_path ///test/test//
996 set -- "${1//+(\/)//}"
1001 # convert_abs_rel <from> <to>
1002 # Prints the relative path, when creating a symlink to <to> from <from>.
1004 # $ convert_abs_rel /usr/bin/test /bin/test-2
1006 # $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
1008 local __current __absolute __abssize __cursize __newpath
1009 local -i __i __level
1011 set -- "$(normalize_path "$1")" "$(normalize_path "$2")"
1013 # corner case #1 - self looping link
1014 [[ "$1" == "$2" ]] && { echo "${1##*/}"; return; }
1016 # corner case #2 - own dir link
1017 [[ "${1%/*}" == "$2" ]] && { echo "."; return; }
1019 IFS
="/" __current
=($1)
1020 IFS
="/" __absolute
=($2)
1022 __abssize
=${#__absolute[@]}
1023 __cursize
=${#__current[@]}
1025 while [[ ${__absolute[__level]} == ${__current[__level]} ]]
1028 if (( __level
> __abssize || __level
> __cursize
))
1034 for ((__i
= __level
; __i
< __cursize-1
; __i
++))
1036 if ((__i
> __level
))
1038 __newpath
=$__newpath"/"
1040 __newpath
=$__newpath".."
1043 for ((__i
= __level
; __i
< __abssize
; __i
++))
1045 if [[ -n $__newpath ]]
1047 __newpath
=$__newpath"/"
1049 __newpath
=$__newpath${__absolute[__i]}
1056 # Install a directory, keeping symlinks as on the original system.
1057 # Example: if /lib points to /lib64 on the host, "inst_dir /lib/file"
1058 # will create ${initdir}/lib64, ${initdir}/lib64/file,
1059 # and a symlink ${initdir}/lib -> lib64.
1061 [[ -e ${initdir}/"$1" ]] && return 0 # already there
1063 local _dir
="$1" _part
="${1%/*}" _file
1064 while [[ "$_part" != "${_part%/*}" ]] && ! [[ -e "${initdir}/${_part}" ]]; do
1069 # iterate over parent directories
1070 for _file
in $_dir; do
1071 [[ -e "${initdir}/$_file" ]] && continue
1072 if [[ -L $_file ]]; then
1073 inst_symlink
"$_file"
1076 mkdir
-m 0755 -p "${initdir}/$_file" ||
return 1
1077 [[ -e "$_file" ]] && chmod --reference="$_file" "${initdir}/$_file"
1078 chmod u
+w
"${initdir}/$_file"
1083 # $1 = file to copy to ramdisk
1084 # $2 (optional) Name for the file on the ramdisk
1085 # Location of the image dir is assumed to be $initdir
1086 # We never overwrite the target if it exists.
1088 [[ -f "$1" ]] ||
return 1
1089 strstr
"$1" "/" ||
return 1
1091 local _src
=$1 target
="${2:-$1}"
1092 if ! [[ -d ${initdir}/$target ]]; then
1093 [[ -e ${initdir}/$target ]] && return 0
1094 [[ -L ${initdir}/$target ]] && return 0
1095 [[ -d "${initdir}/${target%/*}" ]] || inst_dir "${target%/*}"
1097 # install checksum files also
1098 if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then
1099 inst
"${_src%/*}/.${_src##*/}.hmac" "${target%/*}/.${target##*/}.hmac"
1101 ddebug
"Installing $_src"
1102 cp --sparse=always
-pfL "$_src" "${initdir}/$target"
1105 # find symlinks linked to given library file
1107 # Function searches for symlinks by stripping version numbers appended to
1108 # library filename, checks if it points to the same target and finally
1109 # prints the list of symlinks to stdout.
1112 # rev_lib_symlinks libfoo.so.8.1
1113 # output: libfoo.so.8 libfoo.so
1114 # (Only if libfoo.so.8 and libfoo.so exists on host system.)
1115 rev_lib_symlinks
() {
1116 [[ ! $1 ]] && return 0
1118 local fn
="$1" orig
="$(readlink -f "$1")" links
=''
1120 [[ ${fn} =~ .
*\.so\..
* ]] ||
return 1
1122 until [[ ${fn##*.} == so
]]; do
1124 [[ -L ${fn} && $(readlink -f "${fn}") == ${orig} ]] && links+=" ${fn}"
1130 # Same as above, but specialized to handle dynamic libraries.
1131 # It handles making symlinks according to how the original library
1134 local _src="$1" _dest=${2:-$1} _lib _reallib _symlink
1135 strstr "$1" "/" || return 1
1136 [[ -e $initdir/$_dest ]] && return 0
1137 if [[ -L $_src ]]; then
1138 # install checksum files also
1139 if [[ -e "${_src%/*}/.
${_src##*/}.hmac
" ]]; then
1140 inst "${_src%/*}/.${_src##*/}.hmac" "${_dest%/*}/.${_dest##*/}.hmac
"
1142 _reallib=$(readlink -f "$_src")
1143 inst_simple "$_reallib" "$_reallib"
1144 inst_dir "${_dest%/*}"
1145 [[ -d "${_dest%/*}" ]] && _dest=$(readlink -f "${_dest%/*}")/${_dest##*/}
1146 ln -sfn $
(convert_abs_rel
"${_dest}" "${_reallib}") "${initdir}/${_dest}"
1148 inst_simple
"$_src" "$_dest"
1151 # Create additional symlinks. See rev_symlinks description.
1152 for _symlink
in $
(rev_lib_symlinks
$_src) $
(rev_lib_symlinks
$_reallib); do
1153 [[ -e $initdir/$_symlink ]] ||
{
1154 ddebug
"Creating extra symlink: $_symlink"
1155 inst_symlink
$_symlink
1160 # find a binary. If we were not passed the full path directly,
1161 # search in the usual places to find the binary.
1163 if [[ -z ${1##/*} ]]; then
1164 if [[ -x $1 ]] ||
{ strstr
"$1" ".so" && ldd
$1 &>/dev
/null
; }; then
1173 # Same as above, but specialized to install binary executables.
1174 # Install binary executable, and all shared library dependencies, if any.
1177 _bin
=$
(find_binary
"$1") ||
return 1
1179 [[ -e $initdir/$_target ]] && return 0
1180 [[ -L $_bin ]] && inst_symlink
$_bin $_target && return 0
1182 local _so_regex
='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
1184 LC_ALL
=C ldd
"$_bin" 2>/dev
/null |
while read _line
; do
1185 [[ $_line = 'not a dynamic executable' ]] && break
1187 if [[ $_line =~
$_so_regex ]]; then
1188 _file
=${BASH_REMATCH[1]}
1189 [[ -e ${initdir}/$_file ]] && continue
1190 inst_library
"$_file"
1194 if [[ $_line =~ not\ found
]]; then
1195 dfatal
"Missing a shared library required by $_bin."
1196 dfatal
"Run \"ldd $_bin\" to find out what it is."
1198 dfatal
"dracut cannot create an initrd."
1202 inst_simple
"$_bin" "$_target"
1205 # same as above, except for shell scripts.
1206 # If your shell script does not start with shebang, it is not a shell script.
1209 _bin
=$
(find_binary
"$1") ||
return 1
1211 local _line _shebang_regex
1212 read -r -n 80 _line
<"$_bin"
1213 # If debug is set, clean unprintable chars to prevent messing up the term
1214 [[ $debug ]] && _line
=$
(echo -n "$_line" |
tr -c -d '[:print:][:space:]')
1215 _shebang_regex
='(#! *)(/[^ ]+).*'
1216 [[ $_line =~
$_shebang_regex ]] ||
return 1
1217 inst
"${BASH_REMATCH[2]}" && inst_simple
"$_bin" "$@"
1220 # same as above, but specialized for symlinks
1222 local _src
=$1 _target
=${2:-$1} _realsrc
1223 strstr
"$1" "/" ||
return 1
1224 [[ -L $1 ]] ||
return 1
1225 [[ -L $initdir/$_target ]] && return 0
1226 _realsrc
=$
(readlink
-f "$_src")
1227 if ! [[ -e $initdir/$_realsrc ]]; then
1228 if [[ -d $_realsrc ]]; then
1229 inst_dir
"$_realsrc"
1234 [[ ! -e $initdir/${_target%/*} ]] && inst_dir
"${_target%/*}"
1235 [[ -d ${_target%/*} ]] && _target=$(readlink -f ${_target%/*})/${_target##*/}
1236 ln -sfn $
(convert_abs_rel
"${_target}" "${_realsrc}") "$initdir/$_target"
1239 # attempt to install any programs specified in a udev rule
1240 inst_rule_programs
() {
1243 if grep -qE 'PROGRAM==?"[^ "]+' "$1"; then
1244 for _prog
in $
(grep -E 'PROGRAM==?"[^ "]+' "$1" |
sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/'); do
1245 if [ -x /lib
/udev
/$_prog ]; then
1246 _bin
=/lib
/udev
/$_prog
1248 _bin
=$
(find_binary
"$_prog") ||
{
1249 dinfo
"Skipping program $_prog using in udev rule $(basename $1) as it cannot be found"
1254 #dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)"
1255 dracut_install
"$_bin"
1260 # udev rules always get installed in the same place, so
1261 # create a function to install them to make life simpler.
1263 local _target
=/etc
/udev
/rules.d _rule _found
1265 inst_dir
"/lib/udev/rules.d"
1267 for _rule
in "$@"; do
1268 if [ "${rule#/}" = "$rule" ]; then
1269 for r
in /lib
/udev
/rules.d
/etc
/udev
/rules.d
; do
1270 if [[ -f $r/$_rule ]]; then
1272 inst_simple
"$_found"
1273 inst_rule_programs
"$_found"
1277 for r
in '' .
/ $dracutbasedir/rules.d
/; do
1278 if [[ -f ${r}$_rule ]]; then
1280 inst_simple
"$_found" "$_target/${_found##*/}"
1281 inst_rule_programs
"$_found"
1284 [[ $_found ]] || dinfo
"Skipping udev rule: $_rule"
1289 # general purpose installation function
1290 # Same args as above.
1296 2) [[ ! $initdir && -d $2 ]] && export initdir
=$2
1297 [[ $initdir = $2 ]] && set $1;;
1298 3) [[ -z $initdir ]] && export initdir
=$2
1300 *) dfatal
"inst only takes 1 or 2 or 3 arguments"
1303 for _x
in inst_symlink inst_script inst_binary inst_simple
; do
1304 $_x "$@" && return 0
1309 # install any of listed files
1311 # If first argument is '-d' and second some destination path, first accessible
1312 # source is installed into this path, otherwise it will installed in the same
1313 # path as source. If none of listed files was installed, function return 1.
1314 # On first successful installation it returns with 0 status.
1318 # inst_any -d /bin/foo /bin/bar /bin/baz
1320 # Lets assume that /bin/baz exists, so it will be installed as /bin/foo in
1325 [[ $1 = '-d' ]] && to
="$2" && shift 2
1328 if [[ -e $f ]]; then
1329 [[ $to ]] && inst
"$f" "$to" && return 0
1330 inst
"$f" && return 0
1337 # dracut_install [-o ] <file> [<file> ... ]
1338 # Install <file> to the initramfs image
1339 # -o optionally install the <file> and don't fail, if it is not there
1342 if [[ $1 = '-o' ]]; then
1346 while (($# > 0)); do
1347 if ! inst
"$1" ; then
1348 if [[ $_optional = yes ]]; then
1349 dinfo
"Skipping program $1 as it cannot be found and is" \
1350 "flagged to be optional"
1352 dfatal
"Failed to install $1"
1360 # Install a single kernel module along with any firmware it may require.
1361 # $1 = full path to kernel module to install
1362 install_kmod_with_fw
() {
1363 # no need to go further if the module is already installed
1365 [[ -e "${initdir}/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" ]] \
1368 [[ -e "$initdir/.kernelmodseen/${1##*/}" ]] && return 0
1370 if [[ $omit_drivers ]]; then
1371 local _kmod
=${1##*/}
1374 if [[ "$_kmod" =~
$omit_drivers ]]; then
1375 dinfo
"Omitting driver $_kmod"
1378 if [[ "${1##*/lib/modules/$KERNEL_VER/}" =~
$omit_drivers ]]; then
1379 dinfo
"Omitting driver $_kmod"
1384 [ -d "$initdir/.kernelmodseen" ] && \
1385 > "$initdir/.kernelmodseen/${1##*/}"
1387 inst_simple
"$1" "/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" \
1390 local _modname
=${1##*/} _fwdir _found _fw
1391 _modname
=${_modname%.ko*}
1392 for _fw
in $
(modinfo
-k $KERNEL_VER -F firmware
$1 2>/dev
/null
); do
1394 for _fwdir
in $fw_dir; do
1395 if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then
1396 inst_simple
"$_fwdir/$_fw" "/lib/firmware/$_fw"
1400 if [[ $_found != yes ]]; then
1401 if ! grep -qe "\<${_modname//-/_}\>" /proc
/modules
; then
1402 dinfo
"Possible missing firmware \"${_fw}\" for kernel module" \
1403 "\"${_modname}.ko\""
1405 dwarn
"Possible missing firmware \"${_fw}\" for kernel module" \
1406 "\"${_modname}.ko\""
1413 # Do something with all the dependencies of a kernel module.
1414 # Note that kernel modules depend on themselves using the technique we use
1415 # $1 = function to call for each dependency we find
1416 # It will be passed the full path to the found kernel module
1417 # $2 = module to get dependencies for
1418 # rest of args = arguments to modprobe
1419 # _fderr specifies FD passed from surrounding scope
1420 for_each_kmod_dep
() {
1421 local _func
=$1 _kmod
=$2 _cmd _modpath _options _found
=0
1423 modprobe
"$@" --ignore-install --show-depends $_kmod 2>&${_fderr} |
(
1424 while read _cmd _modpath _options
; do
1425 [[ $_cmd = insmod
]] ||
continue
1426 $_func ${_modpath} ||
exit $?
1429 [[ $_found -eq 0 ]] && exit 1
1434 # filter kernel modules to install certain modules that meet specific
1436 # $1 = search only in subdirectory of /kernel/$1
1437 # $2 = function to call with module name to filter.
1438 # This function will be passed the full path to the module to test.
1439 # The behavior of this function can vary depending on whether $hostonly is set.
1440 # If it is, we will only look at modules that are already in memory.
1441 # If it is not, we will look at all kernel modules
1442 # This function returns the full filenames of modules that match $1
1443 filter_kernel_modules_by_path
() (
1444 local _modname _filtercmd
1445 if ! [[ $hostonly ]]; then
1446 _filtercmd
='find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra"'
1447 _filtercmd
+=' "$KERNEL_MODS/weak-updates" -name "*.ko" -o -name "*.ko.gz"'
1448 _filtercmd
+=' -o -name "*.ko.xz"'
1449 _filtercmd
+=' 2>/dev/null'
1451 _filtercmd
='cut -d " " -f 1 </proc/modules|xargs modinfo -F filename '
1452 _filtercmd
+='-k $KERNEL_VER 2>/dev/null'
1454 for _modname
in $
(eval $_filtercmd); do
1456 *.ko
) "$2" "$_modname" && echo "$_modname";;
1457 *.ko.gz
) gzip -dc "$_modname" > $initdir/$$.ko
1458 $2 $initdir/$$.ko
&& echo "$_modname"
1459 rm -f $initdir/$$.ko
1461 *.ko.xz
) xz
-dc "$_modname" > $initdir/$$.ko
1462 $2 $initdir/$$.ko
&& echo "$_modname"
1463 rm -f $initdir/$$.ko
1468 find_kernel_modules_by_path
() (
1469 if ! [[ $hostonly ]]; then
1470 find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra" "$KERNEL_MODS/weak-updates" \
1471 -name "*.ko" -o -name "*.ko.gz" -o -name "*.ko.xz" 2>/dev
/null
1473 cut
-d " " -f 1 </proc
/modules \
1474 |
xargs modinfo
-F filename
-k $KERNEL_VER 2>/dev
/null
1478 filter_kernel_modules
() {
1479 filter_kernel_modules_by_path drivers
"$1"
1482 find_kernel_modules
() {
1483 find_kernel_modules_by_path drivers
1486 # instmods [-c] <kernel module> [<kernel module> ... ]
1487 # instmods [-c] <kernel subsystem>
1488 # install kernel modules along with all their dependencies.
1489 # <kernel subsystem> can be e.g. "=block" or "=drivers/usb/storage"
1491 [[ $no_kernel = yes ]] && return
1492 # called [sub]functions inherit _fderr
1495 if [[ $1 = '-c' ]]; then
1500 function inst1mod
() {
1501 local _ret
=0 _mod
="$1"
1504 if [ -f $KERNEL_MODS/modules.
${_mod#=} ]; then
1505 ( [[ "$_mpargs" ]] && echo $_mpargs
1506 cat "${KERNEL_MODS}/modules.${_mod#=}" ) \
1509 ( [[ "$_mpargs" ]] && echo $_mpargs
1510 find "$KERNEL_MODS" -path "*/${_mod#=}/*" -printf '%f\n' ) \
1514 --*) _mpargs
+=" $_mod" ;;
1515 i2o_scsi
) return ;; # Do not load this diagnostic-only module
1518 # if we are already installed, skip this module and go on
1520 [[ -f "$initdir/.kernelmodseen/${_mod%.ko}.ko" ]] && return
1522 if [[ $omit_drivers ]] && [[ "$1" =~
$omit_drivers ]]; then
1523 dinfo
"Omitting driver ${_mod##$KERNEL_MODS}"
1526 # If we are building a host-specific initramfs and this
1527 # module is not already loaded, move on to the next one.
1528 [[ $hostonly ]] && ! grep -qe "\<${_mod//-/_}\>" /proc
/modules \
1529 && ! echo $add_drivers |
grep -qe "\<${_mod}\>" \
1532 # We use '-d' option in modprobe only if modules prefix path
1533 # differs from default '/'. This allows us to use Dracut with
1534 # old version of modprobe which doesn't have '-d' option.
1535 local _moddirname
=${KERNEL_MODS%%/lib/modules/*}
1536 [[ -n ${_moddirname} ]] && _moddirname
="-d ${_moddirname}/"
1538 # ok, load the module, all its dependencies, and any firmware
1540 for_each_kmod_dep install_kmod_with_fw
$_mod \
1541 --set-version $KERNEL_VER ${_moddirname} $_mpargs
1548 function instmods_1
() {
1550 if (($# == 0)); then # filenames from stdin
1552 inst1mod
"${_mod%.ko*}" ||
{
1553 if [ "$_check" = "yes" ]; then
1554 dfatal
"Failed to install $_mod"
1560 while (($# > 0)); do # filenames as arguments
1561 inst1mod
${1%.ko*} ||
{
1562 if [ "$_check" = "yes" ]; then
1563 dfatal
"Failed to install $1"
1572 local _ret _filter_not_found
='FATAL: Module .* not found.'
1574 # Capture all stderr from modprobe to _fderr. We could use {var}>...
1575 # redirections, but that would make dracut require bash4 at least.
1576 eval "( instmods_1 \"\$@\" ) ${_fderr}>&1" \
1577 |
while read line
; do [[ "$line" =~
$_filter_not_found ]] && echo $line ||
echo $line >&2 ;done | derror
1583 # inst_libdir_file [-n <pattern>] <file> [<file>...]
1584 # Install a <file> located on a lib directory to the initramfs image
1585 # -n <pattern> install non-matching files
1586 inst_libdir_file
() {
1587 if [[ "$1" == "-n" ]]; then
1590 for _dir
in $libdirs; do
1592 for _f
in "$_dir"/$_i; do
1593 [[ "$_i" =~
$_pattern ]] ||
continue
1594 [[ -e "$_i" ]] && dracut_install
"$_i"
1599 for _dir
in $libdirs; do
1601 for _f
in "$_dir"/$_i; do
1602 [[ -e "$_f" ]] && dracut_install
"$_f"
1610 ln -fs ..
/usr
/bin
/systemctl
$initdir/bin
/
1611 ln -fs ..
/usr
/lib
/systemd
$initdir/lib
/
1612 inst_simple
"/usr/lib/systemd/system/haveged.service"
1615 # can be overridden in specific test
1617 umount
$TESTDIR/root
2>/dev
/null || true
1618 [[ $LOOPDEV ]] && losetup
-d $LOOPDEV || true
1623 if [ -z "$TEST_NO_QEMU" ]; then
1625 check_result_qemu ||
return 1
1627 dwarn
"can't run QEMU, skipping"
1630 if [ -z "$TEST_NO_NSPAWN" ]; then
1631 if run_nspawn
"nspawn-root"; then
1632 check_result_nspawn
"nspawn-root" ||
return 1
1634 dwarn
"can't run systemd-nspawn, skipping"
1637 if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then
1638 if NSPAWN_ARGUMENTS
="-U --private-network $NSPAWN_ARGUMENTS" run_nspawn
"unprivileged-nspawn-root"; then
1639 check_result_nspawn
"unprivileged-nspawn-root" ||
return 1
1641 dwarn
"can't run systemd-nspawn, skipping"
1649 if [[ $UID != "0" ]]; then
1650 echo "TEST: $TEST_DESCRIPTION [SKIPPED]: not root" >&2
1655 [[ $libdir ]] ||
for libdir
in /lib64
/lib
; do
1656 [[ -d $libdir ]] && libdirs
+=" $libdir" && break
1659 [[ $usrlibdir ]] ||
for usrlibdir
in /usr
/lib64
/usr
/lib
; do
1660 [[ -d $usrlibdir ]] && libdirs
+=" $usrlibdir" && break
1663 mkdir
-p "$STATEDIR"
1668 while (($# > 0)); do
1671 echo "TEST RUN: $TEST_DESCRIPTION"
1674 if (( $ret == 0 )); then
1675 echo "TEST RUN: $TEST_DESCRIPTION [OK]"
1677 echo "TEST RUN: $TEST_DESCRIPTION [FAILED]"
1681 echo "TEST SETUP: $TEST_DESCRIPTION"
1685 echo "TEST CLEANUP: $TEST_DESCRIPTION"
1692 echo -n "TEST: $TEST_DESCRIPTION ";
1694 test_setup
&& test_run
1700 ) </dev
/null
>"$TESTLOG" 2>&1 || ret
=$?
1701 if [ $ret -eq 0 ]; then