]> git.ipfire.org Git - thirdparty/dracut.git/blob - dracut-init.sh
fix(TEST LVM): shellcheck
[thirdparty/dracut.git] / dracut-init.sh
1 #!/bin/bash
2 #
3 # functions used only by dracut and dracut modules
4 #
5 # Copyright 2005-2009 Red Hat, Inc. All rights reserved.
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #
20 export LC_MESSAGES=C
21
22 if [[ $EUID == "0" ]] && ! [[ $DRACUT_NO_XATTR ]]; then
23 export DRACUT_CP="cp --reflink=auto --sparse=auto --preserve=mode,timestamps,xattr,links -dfr"
24 else
25 export DRACUT_CP="cp --reflink=auto --sparse=auto --preserve=mode,timestamps,links -dfr"
26 fi
27
28 # is_func <command>
29 # Check whether $1 is a function.
30 is_func() {
31 [[ "$(type -t "$1")" == "function" ]]
32 }
33
34 if ! [[ $dracutbasedir ]]; then
35 dracutbasedir=${BASH_SOURCE[0]%/*}
36 [[ $dracutbasedir == dracut-functions* ]] && dracutbasedir="."
37 [[ $dracutbasedir ]] || dracutbasedir="."
38 dracutbasedir="$(readlink -f $dracutbasedir)"
39 fi
40
41 if ! is_func dinfo > /dev/null 2>&1; then
42 # shellcheck source=./dracut-logger.sh
43 . "$dracutbasedir/dracut-logger.sh"
44 dlog_init
45 fi
46
47 # shellcheck disable=SC2154
48 if ! [[ $initdir ]]; then
49 dfatal "initdir not set"
50 exit 1
51 fi
52
53 if ! [[ -d $initdir ]]; then
54 mkdir -p "$initdir"
55 fi
56
57 if ! [[ $kernel ]]; then
58 kernel=$(uname -r)
59 export kernel
60 fi
61
62 # shellcheck disable=SC2154
63 srcmods="$dracutsysrootdir/lib/modules/$kernel/"
64
65 # shellcheck disable=SC2154
66 [[ $drivers_dir ]] && {
67 if ! command -v kmod &> /dev/null && vercmp "$(modprobe --version | cut -d' ' -f3)" lt 3.7; then
68 dfatal 'To use --kmoddir option module-init-tools >= 3.7 is required.'
69 exit 1
70 fi
71 srcmods="$drivers_dir"
72 }
73 export srcmods
74
75 [[ $DRACUT_FIRMWARE_PATH ]] || export DRACUT_FIRMWARE_PATH="/lib/firmware/updates:/lib/firmware:/lib/firmware/$kernel"
76
77 # export standard hookdirs
78 [[ $hookdirs ]] || {
79 hookdirs="cmdline pre-udev pre-trigger netroot "
80 hookdirs+="initqueue initqueue/settled initqueue/online initqueue/finished initqueue/timeout "
81 hookdirs+="pre-mount pre-pivot cleanup mount "
82 hookdirs+="emergency shutdown-emergency pre-shutdown shutdown "
83 export hookdirs
84 }
85
86 DRACUT_LDD=${DRACUT_LDD:-ldd}
87 DRACUT_TESTBIN=${DRACUT_TESTBIN:-/bin/sh}
88 DRACUT_LDCONFIG=${DRACUT_LDCONFIG:-ldconfig}
89
90 # shellcheck source=./dracut-functions.sh
91 . "$dracutbasedir"/dracut-functions.sh
92
93 # Detect lib paths
94 if ! [[ $libdirs ]]; then
95 if [[ $("$DRACUT_LDD" "$dracutsysrootdir$DRACUT_TESTBIN") == */lib64/* ]] &> /dev/null \
96 && [[ -d $dracutsysrootdir/lib64 ]]; then
97 libdirs+=" /lib64"
98 [[ -d $dracutsysrootdir/usr/lib64 ]] && libdirs+=" /usr/lib64"
99 else
100 libdirs+=" /lib"
101 [[ -d $dracutsysrootdir/usr/lib ]] && libdirs+=" /usr/lib"
102 fi
103
104 libdirs+=" $(ldconfig_paths)"
105
106 export libdirs
107 fi
108
109 # helper function for check() in module-setup.sh
110 # to check for required installed binaries
111 # issues a standardized warning message
112 require_binaries() {
113 # shellcheck disable=SC2154
114 local _module_name="${moddir##*/}"
115 local _ret=0
116
117 if [[ $1 == "-m" ]]; then
118 _module_name="$2"
119 shift 2
120 fi
121
122 for cmd in "$@"; do
123 if ! find_binary "$cmd" &> /dev/null; then
124 dinfo "dracut module '${_module_name#[0-9][0-9]}' will not be installed, because command '$cmd' could not be found!"
125 ((_ret++))
126 fi
127 done
128 return "$_ret"
129 }
130
131 require_any_binary() {
132 local _module_name="${moddir##*/}"
133 local _ret=1
134
135 if [[ $1 == "-m" ]]; then
136 _module_name="$2"
137 shift 2
138 fi
139
140 for cmd in "$@"; do
141 if find_binary "$cmd" &> /dev/null; then
142 _ret=0
143 break
144 fi
145 done
146
147 if ((_ret != 0)); then
148 dinfo "$_module_name: Could not find any command of '$*'!"
149 return 1
150 fi
151
152 return 0
153 }
154
155 dracut_need_initqueue() {
156 : > "$initdir/lib/dracut/need-initqueue"
157 }
158
159 dracut_module_included() {
160 # shellcheck disable=SC2154
161 [[ " $mods_to_load $modules_loaded " == *\ $*\ * ]]
162 }
163
164 dracut_no_switch_root() {
165 : > "$initdir/lib/dracut/no-switch-root"
166 }
167
168 dracut_module_path() {
169 local _dir
170
171 # shellcheck disable=SC2231
172 for _dir in "${dracutbasedir}"/modules.d/??${1}; do
173 echo "$_dir"
174 return 0
175 done
176 return 1
177 }
178
179 if ! [[ $DRACUT_INSTALL ]]; then
180 DRACUT_INSTALL=$(find_binary dracut-install)
181 fi
182
183 if ! [[ $DRACUT_INSTALL ]] && [[ -x $dracutbasedir/dracut-install ]]; then
184 DRACUT_INSTALL=$dracutbasedir/dracut-install
185 elif ! [[ $DRACUT_INSTALL ]] && [[ -x $dracutbasedir/install/dracut-install ]]; then
186 DRACUT_INSTALL=$dracutbasedir/install/dracut-install
187 fi
188
189 # Test if dracut-install is a standalone executable with no options.
190 # E.g. DRACUT_INSTALL may be set externally as:
191 # DRACUT_INSTALL="valgrind dracut-install"
192 # or
193 # DRACUT_INSTALL="dracut-install --debug"
194 # in which case the string cannot be tested for being executable.
195 DRINSTALLPARTS=0
196 for i in $DRACUT_INSTALL; do
197 DRINSTALLPARTS=$((DRINSTALLPARTS + 1))
198 done
199
200 if [[ $DRINSTALLPARTS == 1 ]] && ! command -v "$DRACUT_INSTALL" > /dev/null 2>&1; then
201 dfatal "dracut-install not found!"
202 exit 10
203 fi
204
205 if [[ $hostonly == "-h" ]]; then
206 if ! [[ $DRACUT_KERNEL_MODALIASES ]] || ! [[ -f $DRACUT_KERNEL_MODALIASES ]]; then
207 export DRACUT_KERNEL_MODALIASES="${DRACUT_TMPDIR}/modaliases"
208 "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${srcmods:+--kerneldir "$srcmods"} --modalias > "$DRACUT_KERNEL_MODALIASES"
209 fi
210 fi
211
212 [[ $DRACUT_RESOLVE_LAZY ]] || export DRACUT_RESOLVE_DEPS=1
213 inst_dir() {
214 [[ -e ${initdir}/"$1" ]] && return 0 # already there
215 if ! "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} -d "$@"; then
216 derror FAILED: "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} -d "$@"
217 fi
218 }
219
220 inst() {
221 local _hostonly_install
222 if [[ $1 == "-H" ]]; then
223 _hostonly_install="-H"
224 shift
225 fi
226 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
227 # shellcheck disable=SC2154
228 if ! "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@"; then
229 derror FAILED: "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@"
230 fi
231 }
232
233 inst_simple() {
234 local _hostonly_install
235 if [[ $1 == "-H" ]]; then
236 _hostonly_install="-H"
237 shift
238 fi
239 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
240 [[ -e $1 ]] || return 1 # no source
241 if ! "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${_hostonly_install:+-H} "$@"; then
242 derror FAILED: "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${_hostonly_install:+-H} "$@" || :
243 fi
244 }
245
246 inst_symlink() {
247 local _hostonly_install
248 if [[ $1 == "-H" ]]; then
249 _hostonly_install="-H"
250 shift
251 fi
252 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
253 [[ -L $1 ]] || return 1
254 if ! "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@"; then
255 derror FAILED: "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@" || :
256 fi
257 }
258
259 inst_multiple() {
260 local _ret
261 if "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} -a ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$@"; then
262 return 0
263 else
264 _ret=$?
265 derror FAILED: "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} -a ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@" || :
266 return $_ret
267 fi
268 }
269
270 dracut_install() {
271 inst_multiple "$@"
272 }
273
274 dracut_instmods() {
275 local _silent=0
276 local i
277 # shellcheck disable=SC2154
278 [[ $no_kernel == yes ]] && return
279 for i in "$@"; do
280 [[ $i == "--silent" ]] && _silent=1
281 done
282
283 # shellcheck disable=SC2154
284 if ! "$DRACUT_INSTALL" \
285 ${dracutsysrootdir:+-r "$dracutsysrootdir"} \
286 ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${hostonly:+-H} ${omit_drivers:+-N "$omit_drivers"} ${srcmods:+--kerneldir "$srcmods"} -m "$@"; then
287 if ((_silent == 0)); then
288 derror FAILED: "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${hostonly:+-H} ${omit_drivers:+-N "$omit_drivers"} ${srcmods:+--kerneldir "$srcmods"} -m "$@" || :
289 fi
290 fi
291 }
292
293 inst_library() {
294 local _hostonly_install
295 if [[ $1 == "-H" ]]; then
296 _hostonly_install="-H"
297 shift
298 fi
299 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
300 [[ -e $1 ]] || return 1 # no source
301 if ! "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@"; then
302 derror FAILED: "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@" || :
303 fi
304 }
305
306 inst_binary() {
307 if ! "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$@"; then
308 derror FAILED: "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$@" || :
309 fi
310 }
311
312 inst_script() {
313 if ! "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$@"; then
314 derror FAILED: "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$@" || :
315 fi
316 }
317
318 inst_fsck_help() {
319 local _helper="/run/dracut/fsck/fsck_help_$1.txt"
320 if ! "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$2" "$_helper"; then
321 derror "$DRACUT_INSTALL" ${dracutsysrootdir:+-r "$dracutsysrootdir"} ${initdir:+-D "$initdir"} ${loginstall:+-L "$loginstall"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$2" "$_helper" || :
322 fi
323 }
324
325 # Use with form hostonly="$(optional_hostonly)" inst_xxxx <args>
326 # If hosotnly mode is set to "strict", hostonly restrictions will still
327 # be applied, else will ignore hostonly mode and try to install all
328 # given modules.
329 optional_hostonly() {
330 # shellcheck disable=SC2154
331 if [[ $hostonly_mode == "strict" ]]; then
332 printf -- "%s" "$hostonly"
333 else
334 printf ""
335 fi
336 }
337
338 mark_hostonly() {
339 for i in "$@"; do
340 echo "$i" >> "$initdir/lib/dracut/hostonly-files"
341 done
342 }
343
344 # find symlinks linked to given library file
345 # $1 = library file
346 # Function searches for symlinks by stripping version numbers appended to
347 # library filename, checks if it points to the same target and finally
348 # prints the list of symlinks to stdout.
349 #
350 # Example:
351 # rev_lib_symlinks libfoo.so.8.1
352 # output: libfoo.so.8 libfoo.so
353 # (Only if libfoo.so.8 and libfoo.so exists on host system.)
354 rev_lib_symlinks() {
355 local _fn
356 local _orig
357 local _links
358
359 [[ ! $1 ]] && return 0
360
361 _fn="$1"
362 _orig="$(readlink -f "$1")"
363 _links=()
364
365 [[ ${_fn} == *.so.* ]] || return 1
366
367 until [[ ${_fn##*.} == so ]]; do
368 _fn="${_fn%.*}"
369 [[ -L ${_fn} ]] && [[ $(readlink -f "${_fn}") == "${_orig}" ]] && _links+=("${_fn}")
370 done
371
372 echo "${_links[*]}}"
373 }
374
375 # attempt to install any programs specified in a udev rule
376 inst_rule_programs() {
377 local _prog _bin
378
379 # shellcheck disable=SC2013
380 for _prog in $(sed -nr 's/.*PROGRAM==?"([^ "]+).*/\1/p' "$1"); do
381 _bin=""
382 # shellcheck disable=SC2154
383 if [[ -x ${udevdir}/$_prog ]]; then
384 _bin="${udevdir}"/$_prog
385 elif [[ ${_prog/\$env\{/} == "$_prog" ]]; then
386 _bin=$(find_binary "$_prog") || {
387 dinfo "Skipping program $_prog using in udev rule ${1##*/} as it cannot be found"
388 continue
389 }
390 fi
391
392 [[ $_bin ]] && inst_binary "$_bin"
393 done
394
395 # shellcheck disable=SC2013
396 for _prog in $(sed -nr 's/.*RUN[+=]=?"([^ "]+).*/\1/p' "$1"); do
397 _bin=""
398 if [[ -x ${udevdir}/$_prog ]]; then
399 _bin=${udevdir}/$_prog
400 elif [[ ${_prog/\$env\{/} == "$_prog" ]] && [[ ${_prog} != "/sbin/initqueue" ]]; then
401 _bin=$(find_binary "$_prog") || {
402 dinfo "Skipping program $_prog using in udev rule ${1##*/} as it cannot be found"
403 continue
404 }
405 fi
406
407 [[ $_bin ]] && inst_binary "$_bin"
408 done
409
410 # shellcheck disable=SC2013
411 for _prog in $(sed -nr 's/.*IMPORT\{program\}==?"([^ "]+).*/\1/p' "$1"); do
412 _bin=""
413 if [[ -x ${udevdir}/$_prog ]]; then
414 _bin=${udevdir}/$_prog
415 elif [[ ${_prog/\$env\{/} == "$_prog" ]]; then
416 _bin=$(find_binary "$_prog") || {
417 dinfo "Skipping program $_prog using in udev rule ${1##*/} as it cannot be found"
418 continue
419 }
420 fi
421
422 [[ $_bin ]] && dracut_install "$_bin"
423 done
424 }
425
426 # attempt to install any programs specified in a udev rule
427 inst_rule_group_owner() {
428 local i
429
430 # shellcheck disable=SC2013
431 for i in $(sed -nr 's/.*OWNER=?"([^ "]+).*/\1/p' "$1"); do
432 if ! grep -Eq "^$i:" "$initdir/etc/passwd" 2> /dev/null; then
433 grep -E "^$i:" "$dracutsysrootdir"/etc/passwd 2> /dev/null >> "$initdir/etc/passwd"
434 fi
435 done
436
437 # shellcheck disable=SC2013
438 for i in $(sed -nr 's/.*GROUP=?"([^ "]+).*/\1/p' "$1"); do
439 if ! grep -Eq "^$i:" "$initdir/etc/group" 2> /dev/null; then
440 grep -E "^$i:" "$dracutsysrootdir"/etc/group 2> /dev/null >> "$initdir/etc/group"
441 fi
442 done
443 }
444
445 inst_rule_initqueue() {
446 if grep -q -F initqueue "$1"; then
447 dracut_need_initqueue
448 fi
449 }
450
451 # udev rules always get installed in the same place, so
452 # create a function to install them to make life simpler.
453 inst_rules() {
454 local _target=/etc/udev/rules.d _rule _found
455
456 inst_dir "${udevdir}/rules.d"
457 inst_dir "$_target"
458 for _rule in "$@"; do
459 if [ "${_rule#/}" = "$_rule" ]; then
460 for r in "$dracutsysrootdir${udevdir}/rules.d" ${hostonly:+"$dracutsysrootdir"/etc/udev/rules.d}; do
461 [[ -e $r/$_rule ]] || continue
462 _found="$r/$_rule"
463 inst_rule_programs "$_found"
464 inst_rule_group_owner "$_found"
465 inst_rule_initqueue "$_found"
466 inst_simple "$_found"
467 done
468 fi
469 for r in '' "$dracutsysrootdir$dracutbasedir/rules.d/"; do
470 # skip rules without an absolute path
471 [[ "${r}$_rule" != /* ]] && continue
472 [[ -f ${r}$_rule ]] || continue
473 _found="${r}$_rule"
474 inst_rule_programs "$_found"
475 inst_rule_group_owner "$_found"
476 inst_rule_initqueue "$_found"
477 inst_simple "$_found" "$_target/${_found##*/}"
478 done
479 [[ $_found ]] || dinfo "Skipping udev rule: $_rule"
480 done
481 }
482
483 inst_rules_wildcard() {
484 local _target=/etc/udev/rules.d _rule _found
485
486 inst_dir "${udevdir}/rules.d"
487 inst_dir "$_target"
488 for _rule in ${udevdir}/rules.d/$1 ${dracutbasedir}/rules.d/$1; do
489 [[ -e $_rule ]] || continue
490 inst_rule_programs "$_rule"
491 inst_rule_group_owner "$_rule"
492 inst_rule_initqueue "$_rule"
493 inst_simple "$_rule"
494 _found=$_rule
495 done
496 if [[ -n ${hostonly} ]]; then
497 for _rule in ${_target}/$1; do
498 [[ -f $_rule ]] || continue
499 inst_rule_programs "$_rule"
500 inst_rule_group_owner "$_rule"
501 inst_rule_initqueue "$_rule"
502 inst_simple "$_rule"
503 _found=$_rule
504 done
505 fi
506 [[ $_found ]] || dinfo "Skipping udev rule: $_rule"
507 }
508
509 prepare_udev_rules() {
510 if [ -z "$UDEVVERSION" ]; then
511 UDEVVERSION=$(udevadm --version)
512 export UDEVVERSION
513 fi
514
515 if [ -z "$UDEVVERSION" ]; then
516 derror "Failed to detect udev version!"
517 return 1
518 fi
519 if [ -z "${UDEVVERSION##*[!0-9]*}" ]; then
520 derror "udevadm --version did not report an integer, udev version cannot be determined!"
521 return 1
522 fi
523
524 for f in "$@"; do
525 f="${initdir}/etc/udev/rules.d/$f"
526 [ -e "$f" ] || continue
527 while read -r line || [ -n "$line" ]; do
528 if [ "${line%%IMPORT PATH_ID}" != "$line" ]; then
529 if ((UDEVVERSION >= 174)); then
530 printf '%sIMPORT{builtin}="path_id"\n' "${line%%IMPORT PATH_ID}"
531 else
532 printf '%sIMPORT{program}="path_id %%p"\n' "${line%%IMPORT PATH_ID}"
533 fi
534 elif [ "${line%%IMPORT BLKID}" != "$line" ]; then
535 if ((UDEVVERSION >= 176)); then
536 printf '%sIMPORT{builtin}="blkid"\n' "${line%%IMPORT BLKID}"
537 else
538 # shellcheck disable=SC2016
539 printf '%sIMPORT{program}="/sbin/blkid -o udev -p $tempnode"\n' "${line%%IMPORT BLKID}"
540 fi
541 else
542 echo "$line"
543 fi
544 done < "${f}" > "${f}.new"
545 mv "${f}.new" "$f"
546 done
547 }
548
549 # install function specialized for hooks
550 # $1 = type of hook, $2 = hook priority (lower runs first), $3 = hook
551 # All hooks should be POSIX/SuS compliant, they will be sourced by init.
552 inst_hook() {
553 local hook
554 if ! [[ -f $3 ]]; then
555 dfatal "Cannot install a hook ($3) that does not exist."
556 dfatal "Aborting initrd creation."
557 exit 1
558 elif ! [[ $hookdirs == *$1* ]]; then
559 dfatal "No such hook type $1. Aborting initrd creation."
560 exit 1
561 fi
562 hook="/lib/dracut/hooks/${1}/${2}-${3##*/}"
563 inst_simple "$3" "$hook"
564 chmod u+x "$initdir/$hook"
565 }
566
567 # install any of listed files
568 #
569 # If first argument is '-d' and second some destination path, first accessible
570 # source is installed into this path, otherwise it will installed in the same
571 # path as source. If none of listed files was installed, function return 1.
572 # On first successful installation it returns with 0 status.
573 #
574 # Example:
575 #
576 # inst_any -d /bin/foo /bin/bar /bin/baz
577 #
578 # Lets assume that /bin/baz exists, so it will be installed as /bin/foo in
579 # initramfs.
580 inst_any() {
581 local to f
582
583 [[ $1 == '-d' ]] && to="$2" && shift 2
584
585 for f in "$@"; do
586 [[ -e $f ]] || continue
587 [[ $to ]] && inst "$f" "$to" && return 0
588 inst "$f" && return 0
589 done
590
591 return 1
592 }
593
594 # inst_libdir_file [-n <pattern>] <file> [<file>...]
595 # Install a <file> located on a lib directory to the initramfs image
596 # -n <pattern> install matching files
597 inst_libdir_file() {
598 local -a _files
599 if [[ $1 == "-n" ]]; then
600 local _pattern=$2
601 shift 2
602 for _dir in $libdirs; do
603 for _i in "$@"; do
604 for _f in "$dracutsysrootdir$_dir"/$_i; do
605 [[ ${_f#$dracutsysrootdir} =~ $_pattern ]] || continue
606 [[ -e $_f ]] && _files+=("${_f#$dracutsysrootdir}")
607 done
608 done
609 done
610 else
611 for _dir in $libdirs; do
612 for _i in "$@"; do
613 for _f in "$dracutsysrootdir$_dir"/$_i; do
614 [[ -e $_f ]] && _files+=("${_f#$dracutsysrootdir}")
615 done
616 done
617 done
618 fi
619 [[ ${#_files[@]} -gt 0 ]] && inst_multiple "${_files[@]}"
620 }
621
622 # get a command to decompress the given file
623 get_decompress_cmd() {
624 case "$1" in
625 *.gz) echo 'gzip -f -d' ;;
626 *.bz2) echo 'bzip2 -d' ;;
627 *.xz) echo 'xz -f -d' ;;
628 esac
629 }
630
631 # install function decompressing the target and handling symlinks
632 # $@ = list of compressed (gz or bz2) files or symlinks pointing to such files
633 #
634 # Function install targets in the same paths inside overlay but decompressed
635 # and without extensions (.gz, .bz2).
636 inst_decompress() {
637 local _src _cmd
638
639 for _src in "$@"; do
640 _cmd=$(get_decompress_cmd "${_src}")
641 [[ -z ${_cmd} ]] && return 1
642 inst_simple "${_src}"
643 # Decompress with chosen tool. We assume that tool changes name e.g.
644 # from 'name.gz' to 'name'.
645 ${_cmd} "${initdir}${_src}"
646 done
647 }
648
649 # It's similar to above, but if file is not compressed, performs standard
650 # install.
651 # $@ = list of files
652 inst_opt_decompress() {
653 local _src
654
655 for _src in "$@"; do
656 inst_decompress "${_src}" || inst "${_src}"
657 done
658 }
659
660 # module_check <dracut module> [<forced>] [<module path>]
661 # execute the check() function of module-setup.sh of <dracut module>
662 # or the "check" script, if module-setup.sh is not found
663 # "check $hostonly" is called
664 module_check() {
665 local _moddir=$3
666 local _ret
667 local _forced=0
668 local _hostonly=$hostonly
669 [[ -z $_moddir ]] && _moddir=$(dracut_module_path "$1")
670 [ $# -eq 2 ] && _forced=$2
671 [[ -d $_moddir ]] || return 1
672 if [[ ! -f $_moddir/module-setup.sh ]]; then
673 # if we do not have a check script, we are unconditionally included
674 [[ -x $_moddir/check ]] || return 0
675 [[ $_forced != 0 ]] && unset hostonly
676 # don't quote $hostonly to leave argument empty
677 # shellcheck disable=SC2086
678 "$_moddir"/check $hostonly
679 _ret=$?
680 else
681 unset check depends cmdline install installkernel
682 check() { true; }
683 # shellcheck disable=SC1090
684 . "$_moddir"/module-setup.sh
685 is_func check || return 0
686 [[ $_forced != 0 ]] && unset hostonly
687 # don't quote $hostonly to leave argument empty
688 # shellcheck disable=SC2086
689 moddir="$_moddir" check $hostonly
690 _ret=$?
691 unset check depends cmdline install installkernel
692 fi
693 hostonly=$_hostonly
694 return $_ret
695 }
696
697 # module_check_mount <dracut module> [<module path>]
698 # execute the check() function of module-setup.sh of <dracut module>
699 # or the "check" script, if module-setup.sh is not found
700 # "mount_needs=1 check 0" is called
701 module_check_mount() {
702 local _moddir=$2
703 local _ret
704 export mount_needs=1
705 [[ -z $_moddir ]] && _moddir=$(dracut_module_path "$1")
706 [[ -d $_moddir ]] || return 1
707 if [[ ! -f $_moddir/module-setup.sh ]]; then
708 # if we do not have a check script, we are unconditionally included
709 [[ -x $_moddir/check ]] || return 0
710 mount_needs=1 "$_moddir"/check 0
711 _ret=$?
712 else
713 unset check depends cmdline install installkernel
714 check() { false; }
715 # shellcheck disable=SC1090
716 . "$_moddir"/module-setup.sh
717 moddir=$_moddir check 0
718 _ret=$?
719 unset check depends cmdline install installkernel
720 fi
721 unset mount_needs
722 return "$_ret"
723 }
724
725 # module_depends <dracut module> [<module path>]
726 # execute the depends() function of module-setup.sh of <dracut module>
727 # or the "depends" script, if module-setup.sh is not found
728 module_depends() {
729 local _moddir=$2
730 local _ret
731 [[ -z $_moddir ]] && _moddir=$(dracut_module_path "$1")
732 [[ -d $_moddir ]] || return 1
733 if [[ ! -f $_moddir/module-setup.sh ]]; then
734 # if we do not have a check script, we have no deps
735 [[ -x $_moddir/check ]] || return 0
736 "$_moddir"/check -d
737 return $?
738 else
739 unset check depends cmdline install installkernel
740 depends() { true; }
741 # shellcheck disable=SC1090
742 . "$_moddir"/module-setup.sh
743 moddir=$_moddir depends
744 _ret=$?
745 unset check depends cmdline install installkernel
746 return $_ret
747 fi
748 }
749
750 # module_cmdline <dracut module> [<module path>]
751 # execute the cmdline() function of module-setup.sh of <dracut module>
752 # or the "cmdline" script, if module-setup.sh is not found
753 module_cmdline() {
754 local _moddir=$2
755 local _ret
756 [[ -z $_moddir ]] && _moddir=$(dracut_module_path "$1")
757 [[ -d $_moddir ]] || return 1
758 if [[ ! -f $_moddir/module-setup.sh ]]; then
759 # shellcheck disable=SC1090
760 [[ -x $_moddir/cmdline ]] && . "$_moddir/cmdline"
761 return $?
762 else
763 unset check depends cmdline install installkernel
764 cmdline() { true; }
765 # shellcheck disable=SC1090
766 . "$_moddir"/module-setup.sh
767 moddir="$_moddir" cmdline
768 _ret=$?
769 unset check depends cmdline install installkernel
770 return $_ret
771 fi
772 }
773
774 # module_install <dracut module> [<module path>]
775 # execute the install() function of module-setup.sh of <dracut module>
776 # or the "install" script, if module-setup.sh is not found
777 module_install() {
778 local _moddir=$2
779 local _ret
780 [[ -z $_moddir ]] && _moddir=$(dracut_module_path "$1")
781 [[ -d $_moddir ]] || return 1
782 if [[ ! -f $_moddir/module-setup.sh ]]; then
783 # shellcheck disable=SC1090
784 [[ -x $_moddir/install ]] && . "$_moddir/install"
785 return $?
786 else
787 unset check depends cmdline install installkernel
788 install() { true; }
789 # shellcheck disable=SC1090
790 . "$_moddir"/module-setup.sh
791 moddir="$_moddir" install
792 _ret=$?
793 unset check depends cmdline install installkernel
794 return $_ret
795 fi
796 }
797
798 # module_installkernel <dracut module> [<module path>]
799 # execute the installkernel() function of module-setup.sh of <dracut module>
800 # or the "installkernel" script, if module-setup.sh is not found
801 module_installkernel() {
802 local _moddir=$2
803 local _ret
804 [[ -z $_moddir ]] && _moddir=$(dracut_module_path "$1")
805 [[ -d $_moddir ]] || return 1
806 if [[ ! -f $_moddir/module-setup.sh ]]; then
807 # shellcheck disable=SC1090
808 [[ -x $_moddir/installkernel ]] && . "$_moddir/installkernel"
809 return $?
810 else
811 unset check depends cmdline install installkernel
812 installkernel() { true; }
813 # shellcheck disable=SC1090
814 . "$_moddir"/module-setup.sh
815 moddir="$_moddir" installkernel
816 _ret=$?
817 unset check depends cmdline install installkernel
818 return $_ret
819 fi
820 }
821
822 # check_mount <dracut module> [<use_as_dep>] [<module path>]
823 # check_mount checks, if a dracut module is needed for the given
824 # device and filesystem types in "${host_fs_types[@]}"
825 check_mount() {
826 local _mod=$1
827 local _moddir=$3
828 local _ret
829 local _moddep
830
831 [[ -z $_moddir ]] && _moddir=$(dracut_module_path "$1")
832 # shellcheck disable=SC2154
833 [ "${#host_fs_types[@]}" -le 0 ] && return 1
834
835 # If we are already scheduled to be loaded, no need to check again.
836 [[ " $mods_to_load " == *\ $_mod\ * ]] && return 0
837 [[ " $mods_checked_as_dep " == *\ $_mod\ * ]] && return 1
838
839 # This should never happen, but...
840 [[ -d $_moddir ]] || return 1
841
842 [[ $2 ]] || mods_checked_as_dep+=" $_mod "
843
844 # shellcheck disable=SC2154
845 if [[ " $omit_dracutmodules " == *\ $_mod\ * ]]; then
846 return 1
847 fi
848
849 if [[ " $dracutmodules $add_dracutmodules $force_add_dracutmodules" == *\ $_mod\ * ]]; then
850 module_check_mount "$_mod" "$_moddir"
851 ret=$?
852
853 # explicit module, so also accept ret=255
854 [[ $ret == 0 || $ret == 255 ]] || return 1
855 else
856 # module not in our list
857 if [[ $dracutmodules == all ]]; then
858 # check, if we can and should install this module
859 module_check_mount "$_mod" "$_moddir" || return 1
860 else
861 # skip this module
862 return 1
863 fi
864 fi
865
866 for _moddep in $(module_depends "$_mod" "$_moddir"); do
867 # handle deps as if they were manually added
868 [[ " $dracutmodules " == *\ $_mod\ * ]] \
869 && [[ " $dracutmodules " != *\ $_moddep\ * ]] \
870 && dracutmodules+=" $_moddep "
871 [[ " $add_dracutmodules " == *\ $_mod\ * ]] \
872 && [[ " $add_dracutmodules " != *\ $_moddep\ * ]] \
873 && add_dracutmodules+=" $_moddep "
874 [[ " $force_add_dracutmodules " == *\ $_mod\ * ]] \
875 && [[ " $force_add_dracutmodules " != *\ $_moddep\ * ]] \
876 && force_add_dracutmodules+=" $_moddep "
877 # if a module we depend on fail, fail also
878 if ! check_module "$_moddep"; then
879 derror "dracut module '$_mod' depends on '$_moddep', which can't be installed"
880 return 1
881 fi
882 done
883
884 [[ " $mods_to_load " == *\ $_mod\ * ]] \
885 || mods_to_load+=" $_mod "
886
887 return 0
888 }
889
890 # check_module <dracut module> [<use_as_dep>] [<module path>]
891 # check if a dracut module is to be used in the initramfs process
892 # if <use_as_dep> is set, then the process also keeps track
893 # that the modules were checked for the dependency tracking process
894 check_module() {
895 local _mod=$1
896 local _moddir=$3
897 local _ret
898 local _moddep
899
900 [[ -z $_moddir ]] && _moddir=$(dracut_module_path "$1")
901 # If we are already scheduled to be loaded, no need to check again.
902 [[ " $mods_to_load " == *\ $_mod\ * ]] && return 0
903 [[ " $mods_checked_as_dep " == *\ $_mod\ * ]] && return 1
904
905 # This should never happen, but...
906 [[ -d $_moddir ]] || return 1
907
908 [[ $2 ]] || mods_checked_as_dep+=" $_mod "
909
910 if [[ " $omit_dracutmodules " == *\ $_mod\ * ]]; then
911 ddebug "dracut module '$_mod' will not be installed, because it's in the list to be omitted!"
912 return 1
913 fi
914
915 if [[ " $dracutmodules $add_dracutmodules $force_add_dracutmodules" == *\ $_mod\ * ]]; then
916 if [[ " $dracutmodules $force_add_dracutmodules " == *\ $_mod\ * ]]; then
917 module_check "$_mod" 1 "$_moddir"
918 ret=$?
919 else
920 module_check "$_mod" 0 "$_moddir"
921 ret=$?
922 fi
923 # explicit module, so also accept ret=255
924 [[ $ret == 0 || $ret == 255 ]] || return 1
925 else
926 # module not in our list
927 if [[ $dracutmodules == all ]]; then
928 # check, if we can and should install this module
929 module_check "$_mod" 0 "$_moddir"
930 ret=$?
931 if [[ $ret != 0 ]]; then
932 [[ $2 ]] && return 1
933 [[ $ret != 255 ]] && return 1
934 fi
935 else
936 # skip this module
937 return 1
938 fi
939 fi
940
941 for _moddep in $(module_depends "$_mod" "$_moddir"); do
942 # handle deps as if they were manually added
943 [[ " $dracutmodules " == *\ $_mod\ * ]] \
944 && [[ " $dracutmodules " != *\ $_moddep\ * ]] \
945 && dracutmodules+=" $_moddep "
946 [[ " $add_dracutmodules " == *\ $_mod\ * ]] \
947 && [[ " $add_dracutmodules " != *\ $_moddep\ * ]] \
948 && add_dracutmodules+=" $_moddep "
949 [[ " $force_add_dracutmodules " == *\ $_mod\ * ]] \
950 && [[ " $force_add_dracutmodules " != *\ $_moddep\ * ]] \
951 && force_add_dracutmodules+=" $_moddep "
952 # if a module we depend on fail, fail also
953 if ! check_module "$_moddep"; then
954 derror "dracut module '$_mod' depends on '$_moddep', which can't be installed"
955 return 1
956 fi
957 done
958
959 [[ " $mods_to_load " == *\ $_mod\ * ]] \
960 || mods_to_load+=" $_mod "
961
962 return 0
963 }
964
965 # for_each_module_dir <func>
966 # execute "<func> <dracut module> 1 <module path>"
967 for_each_module_dir() {
968 local _modcheck
969 local _mod
970 local _moddir
971 local _func
972 _func=$1
973 for _moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
974 [[ -d $_moddir ]] || continue
975 [[ -e $_moddir/install || -e $_moddir/installkernel || -e \
976 $_moddir/module-setup.sh ]] || continue
977 _mod=${_moddir##*/}
978 _mod=${_mod#[0-9][0-9]}
979 $_func "$_mod" 1 "$_moddir"
980 done
981
982 # Report any missing dracut modules, the user has specified
983 _modcheck="$add_dracutmodules $force_add_dracutmodules"
984 [[ $dracutmodules != all ]] && _modcheck="$_modcheck $dracutmodules"
985 for _mod in $_modcheck; do
986 [[ " $mods_to_load " == *\ $_mod\ * ]] && continue
987
988 [[ " $force_add_dracutmodules " != *\ $_mod\ * ]] \
989 && [[ " $dracutmodules " != *\ $_mod\ * ]] \
990 && [[ " $omit_dracutmodules " == *\ $_mod\ * ]] \
991 && continue
992
993 derror "dracut module '$_mod' cannot be found or installed."
994 [[ " $force_add_dracutmodules " == *\ $_mod\ * ]] && exit 1
995 [[ " $dracutmodules " == *\ $_mod\ * ]] && exit 1
996 [[ " $add_dracutmodules " == *\ $_mod\ * ]] && exit 1
997 done
998 }
999
1000 dracut_kernel_post() {
1001 for _f in modules.builtin.bin modules.builtin modules.order; do
1002 [[ -e $srcmods/$_f ]] && inst_simple "$srcmods/$_f" "/lib/modules/$kernel/$_f"
1003 done
1004
1005 # generate module dependencies for the initrd
1006 if [[ -d $initdir/lib/modules/$kernel ]] \
1007 && ! depmod -a -b "$initdir" "$kernel"; then
1008 dfatal "\"depmod -a $kernel\" failed."
1009 exit 1
1010 fi
1011
1012 }
1013
1014 instmods() {
1015 # instmods [-c [-s]] <kernel module> [<kernel module> ... ]
1016 # instmods [-c [-s]] <kernel subsystem>
1017 # install kernel modules along with all their dependencies.
1018 # <kernel subsystem> can be e.g. "=block" or "=drivers/usb/storage"
1019 # -c check
1020 # -s silent
1021 local _optional="-o"
1022 local _silent
1023 local _ret
1024
1025 [[ $no_kernel == yes ]] && return
1026
1027 if [[ $1 == '-c' ]]; then
1028 unset _optional
1029 shift
1030 fi
1031 if [[ $1 == '-s' ]]; then
1032 _silent=1
1033 shift
1034 fi
1035
1036 if (($# == 0)); then
1037 read -r -d '' -a args
1038 set -- "${args[@]}"
1039 fi
1040
1041 if (($# == 0)); then
1042 return 0
1043 fi
1044
1045 "$DRACUT_INSTALL" \
1046 ${initdir:+-D "$initdir"} \
1047 ${dracutsysrootdir:+-r "$dracutsysrootdir"} \
1048 ${loginstall:+-L "$loginstall"} \
1049 ${hostonly:+-H} \
1050 ${omit_drivers:+-N "$omit_drivers"} \
1051 ${srcmods:+--kerneldir "$srcmods"} \
1052 ${_optional:+-o} \
1053 ${_silent:+--silent} \
1054 -m "$@"
1055 _ret=$?
1056
1057 if ((_ret != 0)) && [[ -z $_silent ]]; then
1058 derror "FAILED: " \
1059 "$DRACUT_INSTALL" \
1060 ${initdir:+-D "$initdir"} \
1061 ${dracutsysrootdir:+-r "$dracutsysrootdir"} \
1062 ${loginstall:+-L "$loginstall"} \
1063 ${hostonly:+-H} \
1064 ${omit_drivers:+-N "$omit_drivers"} \
1065 ${srcmods:+--kerneldir "$srcmods"} \
1066 ${_optional:+-o} \
1067 ${_silent:+--silent} \
1068 -m "$@"
1069 fi
1070
1071 [[ "$optional" ]] && return 0
1072 return $_ret
1073 }
1074
1075 if [[ "$(ln --help)" == *--relative* ]]; then
1076 ln_r() {
1077 ln -sfnr "${initdir}/$1" "${initdir}/$2"
1078 }
1079 else
1080 ln_r() {
1081 local _source=$1
1082 local _dest=$2
1083 [[ -d ${_dest%/*} ]] && _dest=$(readlink -f "${_dest%/*}")/${_dest##*/}
1084 ln -sfn -- "$(convert_abs_rel "${_dest}" "${_source}")" "${initdir}/${_dest}"
1085 }
1086 fi
1087
1088 is_qemu_virtualized() {
1089 # 0 if a virt environment was detected
1090 # 1 if a virt environment could not be detected
1091 # 255 if any error was encountered
1092 if type -P systemd-detect-virt > /dev/null 2>&1; then
1093 if ! vm=$(systemd-detect-virt --vm > /dev/null 2>&1); then
1094 return 255
1095 fi
1096 [[ $vm == "qemu" ]] && return 0
1097 [[ $vm == "kvm" ]] && return 0
1098 [[ $vm == "bochs" ]] && return 0
1099 fi
1100
1101 for i in /sys/class/dmi/id/*_vendor; do
1102 [[ -f $i ]] || continue
1103 read -r vendor < "$i"
1104 [[ $vendor == "QEMU" ]] && return 0
1105 [[ $vendor == "Red Hat" ]] && return 0
1106 [[ $vendor == "Bochs" ]] && return 0
1107 done
1108 return 1
1109 }