]> git.ipfire.org Git - thirdparty/dracut.git/blame - dracut-functions.sh
dracut-install.c: try clone ioctl for more speed
[thirdparty/dracut.git] / dracut-functions.sh
CommitLineData
04b56f3a 1#!/bin/bash
cc02093d
HH
2# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3# ex: ts=8 sw=4 sts=4 et filetype=sh
04b56f3a 4#
33ee031c 5# functions used by dracut and other tools.
04b56f3a 6#
33ee031c 7# Copyright 2005-2009 Red Hat, Inc. All rights reserved.
04b56f3a
JK
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
0f9c78c1 20# along with this program. If not, see <http://www.gnu.org/licenses/>.
04b56f3a 21#
04b56f3a 22
70c6b773 23[[ -d "$initdir/.kernelmodseen" ]] || mkdir -p "$initdir/.kernelmodseen"
ec1aa3bc 24
8d95b8b3 25# Generic substring function. If $2 is in $1, return 0.
520047c3 26strstr() { [[ $1 = *$2* ]]; }
8d95b8b3 27
0874654c
HH
28if ! [[ $dracutbasedir ]]; then
29 dracutbasedir=${BASH_SOURCE[0]%/*}
30 [[ $dracutbasedir = "dracut-functions" ]] && dracutbasedir="."
31 [[ $dracutbasedir ]] || dracutbasedir="."
32 dracutbasedir="$(readlink -f $dracutbasedir)"
33fi
34
8d95b8b3
HH
35# Detect lib paths
36if ! [[ $libdirs ]] ; then
37 if strstr "$(ldd /bin/sh)" "/lib64/" &>/dev/null \
38 && [[ -d /lib64 ]]; then
39 libdirs+=" /lib64"
40 [[ -d /usr/lib64 ]] && libdirs+=" /usr/lib64"
41 else
42 libdirs+=" /lib"
43 [[ -d /usr/lib ]] && libdirs+=" /usr/lib"
44 fi
45 export libdirs
46fi
47
48if ! [[ $kernel ]]; then
49 kernel=$(uname -r)
50 export kernel
51fi
52
53srcmods="/lib/modules/$kernel/"
54[[ $drivers_dir ]] && {
55 if vercmp $(modprobe --version | cut -d' ' -f3) lt 3.7; then
56 dfatal 'To use --kmoddir option module-init-tools >= 3.7 is required.'
57 exit 1
58 fi
59 srcmods="$drivers_dir"
60}
61export srcmods
62
d6d53f60 63if ! type dinfo >/dev/null 2>&1; then
552ecca6 64 . "$dracutbasedir/dracut-logger.sh"
e103615b
65 dlog_init
66fi
67
7e2bca48
HH
68# export standard hookdirs
69[[ $hookdirs ]] || {
4fed3ddf 70 hookdirs="cmdline pre-udev pre-trigger netroot "
6e3cc00f 71 hookdirs+="initqueue initqueue/settled initqueue/online initqueue/finished initqueue/timeout "
eef7649e
HH
72 hookdirs+="pre-mount pre-pivot cleanup mount "
73 hookdirs+="emergency shutdown-emergency shutdown "
7e2bca48
HH
74 export hookdirs
75}
76
87122afc
77# Create all subdirectories for given path without creating the last element.
78# $1 = path
f8be7528 79mksubdirs() { [[ -e ${1%/*} ]] || mkdir -m 0755 -p ${1%/*}; }
87122afc 80
22ecea45
81# Version comparision function. Assumes Linux style version scheme.
82# $1 = version a
83# $2 = comparision op (gt, ge, eq, le, lt, ne)
84# $3 = version b
ecf42850 85vercmp() {
29b10e65 86 local _n1=(${1//./ }) _op=$2 _n2=(${3//./ }) _i _res
ecf42850 87
29b10e65 88 for ((_i=0; ; _i++))
22ecea45 89 do
29b10e65
HH
90 if [[ ! ${_n1[_i]}${_n2[_i]} ]]; then _res=0
91 elif ((${_n1[_i]:-0} > ${_n2[_i]:-0})); then _res=1
92 elif ((${_n1[_i]:-0} < ${_n2[_i]:-0})); then _res=2
22ecea45
93 else continue
94 fi
95 break
ecf42850 96 done
ecf42850 97
29b10e65
HH
98 case $_op in
99 gt) ((_res == 1));;
100 ge) ((_res != 2));;
101 eq) ((_res == 0));;
102 le) ((_res != 1));;
103 lt) ((_res == 2));;
104 ne) ((_res != 0));;
22ecea45 105 esac
ecf42850
106}
107
7e2bca48
HH
108# is_func <command>
109# Check whether $1 is a function.
95d2dabc 110is_func() {
0b706743 111 [[ $(type -t $1) = "function" ]]
95d2dabc
HH
112}
113
87122afc
114# Function prints global variables in format name=value line by line.
115# $@ = list of global variables' name
116print_vars() {
29b10e65 117 local _var _value
87122afc 118
29b10e65 119 for _var in $@
87122afc 120 do
29b10e65
HH
121 _value=$(eval echo \$$_var)
122 [[ ${_value} ]] && echo "${_var}=\"${_value}\""
87122afc
123 done
124}
125
7e2bca48
HH
126# normalize_path <path>
127# Prints the normalized path, where it removes any duplicated
128# and trailing slashes.
129# Example:
130# $ normalize_path ///test/test//
131# /test/test
626d9eba 132normalize_path() {
c44e3cb4
MS
133 shopt -q -s extglob
134 set -- "${1//+(\/)//}"
135 shopt -q -u extglob
136 echo "${1%/}"
626d9eba 137}
d4bb4316 138
7e2bca48
HH
139# convert_abs_rel <from> <to>
140# Prints the relative path, when creating a symlink to <to> from <from>.
141# Example:
142# $ convert_abs_rel /usr/bin/test /bin/test-2
143# ../../bin/test-2
144# $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
d4bb4316 145convert_abs_rel() {
6d2a7942 146 local __current __absolute __abssize __cursize __newpath
c44e3cb4 147 local -i __i __level
d4bb4316 148
c44e3cb4
MS
149 set -- "$(normalize_path "$1")" "$(normalize_path "$2")"
150
c1609dd4
MS
151 # corner case #1 - self looping link
152 [[ "$1" == "$2" ]] && { echo "${1##*/}"; return; }
153
154 # corner case #2 - own dir link
155 [[ "${1%/*}" == "$2" ]] && { echo "."; return; }
156
6d2a7942
HH
157 IFS="/" __current=($1)
158 IFS="/" __absolute=($2)
d4bb4316
HH
159
160 __abssize=${#__absolute[@]}
161 __cursize=${#__current[@]}
162
163 while [[ ${__absolute[__level]} == ${__current[__level]} ]]
164 do
165 (( __level++ ))
166 if (( __level > __abssize || __level > __cursize ))
167 then
168 break
169 fi
170 done
171
172 for ((__i = __level; __i < __cursize-1; __i++))
173 do
174 if ((__i > __level))
175 then
176 __newpath=$__newpath"/"
177 fi
178 __newpath=$__newpath".."
179 done
180
181 for ((__i = __level; __i < __abssize; __i++))
182 do
183 if [[ -n $__newpath ]]
184 then
185 __newpath=$__newpath"/"
186 fi
187 __newpath=$__newpath${__absolute[__i]}
188 done
189
190 echo "$__newpath"
191}
192
7224913d 193if strstr "$(ln --help)" "--relative"; then
a20d24de
HH
194 ln_r() {
195 ln -sfnr "${initdir}/$1" "${initdir}/$2"
196 }
197else
198 ln_r() {
199 local _source=$1
200 local _dest=$2
201 [[ -d "${_dest%/*}" ]] && _dest=$(readlink -f "${_dest%/*}")/${_dest##*/}
202 ln -sfn $(convert_abs_rel "${_dest}" "${_source}") "${initdir}/${_dest}"
203 }
204fi
205
7e2bca48
HH
206# get_fs_env <device>
207# Get and set the ID_FS_TYPE and ID_FS_UUID variable from udev for a device.
208# Example:
209# $ get_fs_env /dev/sda2; echo $ID_FS_TYPE; echo $ID_FS_UUID
210# ext4
211# 551a39aa-4ae9-4e70-a262-ef665cadb574
9ede1929 212get_fs_env() {
0e979d48
HH
213 local evalstr
214 local found
215
7c179686 216 [[ $1 ]] || return
29b10e65
HH
217 unset ID_FS_TYPE
218 unset ID_FS_UUID
0e979d48
HH
219 if evalstr=$(udevadm info --query=env --name=$1 \
220 | { while read line; do
221 strstr "$line" "DEVPATH" && found=1;
222 strstr "$line" "ID_FS_TYPE=" && { echo $line; exit 0;}
223 done; [[ $found ]] && exit 0; exit 1; }) ; then
224 eval $evalstr
225 [[ $ID_FS_TYPE ]] && return 0
226 return 1
227 fi
d8b9844c 228
0e979d48 229 # Fallback, if we don't have udev information
a5cde2dd 230 if find_binary blkid >/dev/null; then
66b750a0 231 eval $(blkid -o udev $1 \
a5cde2dd
HH
232 | while read line; do
233 strstr "$line" "ID_FS_TYPE=" && echo $line;
234 done)
235 [[ $ID_FS_TYPE ]] && return 0
7c179686 236 fi
a5cde2dd
HH
237 return 1
238}
9ede1929 239
7e2bca48
HH
240# get_maj_min <device>
241# Prints the major and minor of a device node.
242# Example:
243# $ get_maj_min /dev/sda2
244# 8:2
480d772f
HH
245get_maj_min() {
246 local _dev
74132a10 247 _dev=$(stat -L -c '$((0x%t)):$((0x%T))' "$1" 2>/dev/null)
480d772f
HH
248 _dev=$(eval "echo $_dev")
249 echo $_dev
250}
251
7e2bca48
HH
252# find_block_device <mountpoint>
253# Prints the major and minor number of the block device
254# for a given mountpoint.
255# Unless $use_fstab is set to "yes" the functions
256# uses /proc/self/mountinfo as the primary source of the
257# information and only falls back to /etc/fstab, if the mountpoint
258# is not found there.
259# Example:
260# $ find_block_device /usr
261# 8:4
f76ef3aa 262find_block_device() {
29b10e65 263 local _x _mpt _majmin _dev _fs _maj _min
0b706743 264 if [[ $use_fstab != yes ]]; then
29b10e65 265 while read _x _x _majmin _x _mpt _x _x _fs _dev _x; do
7ae5d9d1 266 [[ $_mpt = $1 ]] || continue
29b10e65
HH
267 [[ $_fs = nfs ]] && { echo $_dev; return 0;}
268 [[ $_fs = nfs3 ]] && { echo $_dev; return 0;}
269 [[ $_fs = nfs4 ]] && { echo $_dev; return 0;}
270 [[ $_fs = btrfs ]] && {
480d772f
HH
271 get_maj_min $_dev
272 return 0;
51c977d1 273 }
7ae5d9d1 274 if [[ ${_majmin#0:} = $_majmin ]]; then
29b10e65 275 echo $_majmin
cc02093d
HH
276 return 0 # we have a winner!
277 fi
0b706743 278 done < /proc/self/mountinfo
7c179686 279 fi
0b706743 280 # fall back to /etc/fstab
29b10e65 281 while read _dev _mpt _fs _x; do
85f8bb16
HH
282 [ "${_dev%%#*}" != "$_dev" ] && continue
283
29b10e65
HH
284 if [[ $_mpt = $1 ]]; then
285 [[ $_fs = nfs ]] && { echo $_dev; return 0;}
286 [[ $_fs = nfs3 ]] && { echo $_dev; return 0;}
287 [[ $_fs = nfs4 ]] && { echo $_dev; return 0;}
288 [[ $_dev != ${_dev#UUID=} ]] && _dev=/dev/disk/by-uuid/${_dev#UUID=}
289 [[ $_dev != ${_dev#LABEL=} ]] && _dev=/dev/disk/by-label/${_dev#LABEL=}
290 [[ -b $_dev ]] || return 1 # oops, not a block device.
c4e48eae 291 get_maj_min "$_dev" && return 0
cc02093d 292 fi
7c179686 293 done < /etc/fstab
0b706743
294
295 return 1
17829e94
VL
296}
297
7e2bca48
HH
298# find_dev_fstype <device>
299# Echo the filesystem type for a given device.
300# /proc/self/mountinfo is taken as the primary source of information
301# and /etc/fstab is used as a fallback.
302# No newline is appended!
303# Example:
304# $ find_dev_fstype /dev/sda2;echo
305# ext4
7ae5d9d1
HH
306find_dev_fstype() {
307 local _x _mpt _majmin _dev _fs _maj _min
308 while read _x _x _majmin _x _mpt _x _x _fs _dev _x; do
309 [[ $_dev = $1 ]] || continue
310 echo -n $_fs;
311 return 0;
312 done < /proc/self/mountinfo
313
314 # fall back to /etc/fstab
315 while read _dev _mpt _fs _x; do
316 [[ $_dev = $1 ]] || continue
317 echo -n $_fs;
318 return 0;
319 done < /etc/fstab
320
321 return 1
322}
323
324# finds the major:minor of the block device backing the root filesystem.
f76ef3aa
VL
325find_root_block_device() { find_block_device /; }
326
7e2bca48
HH
327# for_each_host_dev_fs <func>
328# Execute "<func> <dev> <filesystem>" for every "<dev>|<fs>" pair found
329# in ${host_fs_types[@]}
480d772f
HH
330for_each_host_dev_fs()
331{
332 local _func="$1"
d0096de7
AW
333 local _dev
334 local _fs
2efa546f 335 local _ret=1
480d772f
HH
336 for f in ${host_fs_types[@]}; do
337 OLDIFS="$IFS"
338 IFS="|"
339 set -- $f
340 IFS="$OLDIFS"
d0096de7
AW
341 _dev="$1"
342 [[ -b "$_dev" ]] || continue
343 _fs="$2"
2efa546f 344 $_func $_dev $_fs && _ret=0
480d772f 345 done
2efa546f 346 return $_ret
480d772f
HH
347}
348
17829e94
VL
349# Walk all the slave relationships for a given block device.
350# Stop when our helper function returns success
351# $1 = function to call on every found block device
352# $2 = block device in major:minor format
0b706743 353check_block_and_slaves() {
29b10e65 354 local _x
17829e94
VL
355 [[ -b /dev/block/$2 ]] || return 1 # Not a block device? So sorry.
356 "$1" $2 && return
533d7dc4 357 check_vol_slaves "$@" && return 0
3478b314 358 if [[ -f /sys/dev/block/$2/../dev ]]; then
0b706743 359 check_block_and_slaves $1 $(cat "/sys/dev/block/$2/../dev") && return 0
a3afcf2a 360 fi
17829e94 361 [[ -d /sys/dev/block/$2/slaves ]] || return 1
29b10e65
HH
362 for _x in /sys/dev/block/$2/slaves/*/dev; do
363 [[ -f $_x ]] || continue
364 check_block_and_slaves $1 $(cat "$_x") && return 0
17829e94
VL
365 done
366 return 1
367}
368
533d7dc4
HH
369# ugly workaround for the lvm design
370# There is no volume group device,
371# so, there are no slave devices for volume groups.
372# Logical volumes only have the slave devices they really live on,
373# but you cannot create the logical volume without the volume group.
95bde758 374# And the volume group might be bigger than the devices the LV needs.
533d7dc4 375check_vol_slaves() {
29b10e65 376 local _lv _vg _pv
0b706743 377 for i in /dev/mapper/*; do
c4e48eae 378 _lv=$(get_maj_min $i)
29b10e65
HH
379 if [[ $_lv = $2 ]]; then
380 _vg=$(lvm lvs --noheadings -o vg_name $i 2>/dev/null)
cc02093d 381 # strip space
29b10e65
HH
382 _vg=$(echo $_vg)
383 if [[ $_vg ]]; then
384 for _pv in $(lvm vgs --noheadings -o pv_name "$_vg" 2>/dev/null)
0b706743 385 do
c4e48eae 386 check_block_and_slaves $1 $(get_maj_min $_pv) && return 0
cc02093d
HH
387 done
388 fi
389 fi
533d7dc4
HH
390 done
391 return 1
392}
393
89d44e72
HH
394if [[ -x /usr/bin/dracut-install ]]; then
395 [[ $DRACUT_RESOLVE_LAZY ]] || export DRACUT_RESOLVE_DEPS=1
396 inst_dir() {
397 [[ -e ${initdir}/"$1" ]] && return 0 # already there
398 dracut-install ${initdir+-D "$initdir"} -d "$@"
399 (($? != 0)) && derror dracut-install ${initdir+-D "$initdir"} -d "$@" || :
400 }
19612483 401
89d44e72
HH
402 inst() {
403 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
404 #dinfo "dracut-install -l $@"
405 dracut-install ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
406 (($? != 0)) && derror dracut-install ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
407 }
408
409 inst_simple() {
410 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
411 [[ -e $1 ]] || return 1 # no source
412 dracut-install ${initdir+-D "$initdir"} "$@"
413 (($? != 0)) && derror dracut-install ${initdir+-D "$initdir"} "$@" || :
414 }
415
416 inst_symlink() {
417 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
418 [[ -L $1 ]] || return 1
419 dracut-install ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
420 (($? != 0)) && derror dracut-install ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
421 }
422
423 dracut_install() {
424 #dinfo "initdir=$initdir dracut-install -l $@"
425 dracut-install ${initdir+-D "$initdir"} -a ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
426 (($? != 0)) && derror dracut-install ${initdir+-D "$initdir"} -a ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
427 }
428
429 inst_library() {
430 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
431 [[ -e $1 ]] || return 1 # no source
432 dracut-install ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
433 (($? != 0)) && derror dracut-install ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
434 }
435
436 inst_binary() {
437 dracut-install ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
438 (($? != 0)) && derror dracut-install ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
439 }
440
441 inst_script() {
442 dracut-install ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
443 (($? != 0)) && derror dracut-install ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
444 }
445
446else
447
448 # Install a directory, keeping symlinks as on the original system.
449 # Example: if /lib points to /lib64 on the host, "inst_dir /lib/file"
450 # will create ${initdir}/lib64, ${initdir}/lib64/file,
451 # and a symlink ${initdir}/lib -> lib64.
452 inst_dir() {
453 [[ -e ${initdir}/"$1" ]] && return 0 # already there
454
455 local _dir="$1" _part="${1%/*}" _file
456 while [[ "$_part" != "${_part%/*}" ]] && ! [[ -e "${initdir}/${_part}" ]]; do
457 _dir="$_part $_dir"
458 _part=${_part%/*}
459 done
460
461 # iterate over parent directories
462 for _file in $_dir; do
463 [[ -e "${initdir}/$_file" ]] && continue
464 if [[ -L $_file ]]; then
465 inst_symlink "$_file"
466 else
19612483 467 # create directory
89d44e72
HH
468 mkdir -m 0755 -p "${initdir}/$_file" || return 1
469 [[ -e "$_file" ]] && chmod --reference="$_file" "${initdir}/$_file"
470 chmod u+w "${initdir}/$_file"
471 fi
472 done
473 }
474
475 # $1 = file to copy to ramdisk
476 # $2 (optional) Name for the file on the ramdisk
477 # Location of the image dir is assumed to be $initdir
478 # We never overwrite the target if it exists.
479 inst_simple() {
480 [[ -f "$1" ]] || return 1
481 strstr "$1" "/" || return 1
482 local _src=$1 _target="${2:-$1}"
483
484 [[ -L $_src ]] && { inst_symlink $_src $_target; return $?; }
485
486 if ! [[ -d ${initdir}/$_target ]]; then
487 [[ -e ${initdir}/$_target ]] && return 0
488 [[ -L ${initdir}/$_target ]] && return 0
489 [[ -d "${initdir}/${_target%/*}" ]] || inst_dir "${_target%/*}"
19612483 490 fi
89d44e72
HH
491 if [[ $DRACUT_FIPS_MODE ]]; then
492 # install checksum files also
493 if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then
494 inst "${_src%/*}/.${_src##*/}.hmac" "${_target%/*}/.${_target##*/}.hmac"
495 fi
496 fi
497 ddebug "Installing $_src"
498 cp --reflink=auto --sparse=auto -pfL "$_src" "${initdir}/$_target"
499 }
19612483 500
89d44e72
HH
501 # same as above, but specialized for symlinks
502 inst_symlink() {
503 local _src=$1 _target=${2:-$1} _realsrc
504 strstr "$1" "/" || return 1
505 [[ -L $1 ]] || return 1
506 [[ -L $initdir/$_target ]] && return 0
507 _realsrc=$(readlink -f "$_src")
508 if ! [[ -e $initdir/$_realsrc ]]; then
509 if [[ -d $_realsrc ]]; then
510 inst_dir "$_realsrc"
511 else
512 inst "$_realsrc"
513 fi
514 fi
515 [[ ! -e $initdir/${_target%/*} ]] && inst_dir "${_target%/*}"
3f590c78 516
89d44e72
HH
517 ln_r "${_realsrc}" "${_target}"
518 }
22048b44 519
89d44e72
HH
520 # Same as above, but specialized to handle dynamic libraries.
521 # It handles making symlinks according to how the original library
522 # is referenced.
523 inst_library() {
524 local _src="$1" _dest=${2:-$1} _lib _reallib _symlink
525 strstr "$1" "/" || return 1
526 [[ -e $initdir/$_dest ]] && return 0
527 if [[ -L $_src ]]; then
528 if [[ $DRACUT_FIPS_MODE ]]; then
529 # install checksum files also
530 if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then
531 inst "${_src%/*}/.${_src##*/}.hmac" "${_dest%/*}/.${_dest##*/}.hmac"
532 fi
533 fi
534 _reallib=$(readlink -f "$_src")
535 inst_simple "$_reallib" "$_reallib"
536 inst_dir "${_dest%/*}"
537 ln_r "${_reallib}" "${_dest}"
538 else
539 inst_simple "$_src" "$_dest"
540 fi
22048b44 541
89d44e72
HH
542 # Create additional symlinks. See rev_symlinks description.
543 for _symlink in $(rev_lib_symlinks $_src) $(rev_lib_symlinks $_reallib); do
544 [[ ! -e $initdir/$_symlink ]] && {
545 ddebug "Creating extra symlink: $_symlink"
546 inst_symlink $_symlink
547 }
548 done
549 }
550
551 # Same as above, but specialized to install binary executables.
552 # Install binary executable, and all shared library dependencies, if any.
553 inst_binary() {
554 local _bin _target
555 _bin=$(find_binary "$1") || return 1
556 _target=${2:-$_bin}
557 [[ -e $initdir/$_target ]] && return 0
558 local _file _line
559 local _so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
560 # I love bash!
561 LC_ALL=C ldd "$_bin" 2>/dev/null | while read _line; do
562 [[ $_line = 'not a dynamic executable' ]] && break
563
564 if [[ $_line =~ $_so_regex ]]; then
565 _file=${BASH_REMATCH[1]}
566 [[ -e ${initdir}/$_file ]] && continue
567 inst_library "$_file"
568 continue
569 fi
570
571 if [[ $_line =~ not\ found ]]; then
572 dfatal "Missing a shared library required by $_bin."
573 dfatal "Run \"ldd $_bin\" to find out what it is."
574 dfatal "$_line"
575 dfatal "dracut cannot create an initrd."
576 exit 1
577 fi
578 done
579 inst_simple "$_bin" "$_target"
580 }
581
582 # same as above, except for shell scripts.
583 # If your shell script does not start with shebang, it is not a shell script.
584 inst_script() {
585 local _bin
586 _bin=$(find_binary "$1") || return 1
587 shift
588 local _line _shebang_regex
589 read -r -n 80 _line <"$_bin"
590 # If debug is set, clean unprintable chars to prevent messing up the term
591 [[ $debug ]] && _line=$(echo -n "$_line" | tr -c -d '[:print:][:space:]')
592 _shebang_regex='(#! *)(/[^ ]+).*'
593 [[ $_line =~ $_shebang_regex ]] || return 1
594 inst "${BASH_REMATCH[2]}" && inst_simple "$_bin" "$@"
595 }
596
597 # general purpose installation function
598 # Same args as above.
599 inst() {
600 local _x
601
602 case $# in
603 1) ;;
604 2) [[ ! $initdir && -d $2 ]] && export initdir=$2
605 [[ $initdir = $2 ]] && set $1;;
606 3) [[ -z $initdir ]] && export initdir=$2
607 set $1 $3;;
608 *) dfatal "inst only takes 1 or 2 or 3 arguments"
609 exit 1;;
610 esac
611 for _x in inst_symlink inst_script inst_binary inst_simple; do
612 $_x "$@" && return 0
613 done
614 return 1
615 }
616
617 # dracut_install [-o ] <file> [<file> ... ]
618 # Install <file> to the initramfs image
619 # -o optionally install the <file> and don't fail, if it is not there
620 dracut_install() {
621 local _optional=no
622 if [[ $1 = '-o' ]]; then
623 _optional=yes
624 shift
625 fi
626 while (($# > 0)); do
627 if ! inst "$1" ; then
628 if [[ $_optional = yes ]]; then
629 dinfo "Skipping program $1 as it cannot be found and is" \
630 "flagged to be optional"
631 else
632 dfatal "Failed to install $1"
633 exit 1
634 fi
635 fi
636 shift
637 done
638 }
639
640fi
36b24d7c 641
a10a1416
642# find symlinks linked to given library file
643# $1 = library file
644# Function searches for symlinks by stripping version numbers appended to
645# library filename, checks if it points to the same target and finally
646# prints the list of symlinks to stdout.
647#
648# Example:
649# rev_lib_symlinks libfoo.so.8.1
650# output: libfoo.so.8 libfoo.so
651# (Only if libfoo.so.8 and libfoo.so exists on host system.)
652rev_lib_symlinks() {
653 [[ ! $1 ]] && return 0
654
655 local fn="$1" orig="$(readlink -f "$1")" links=''
656
657 [[ ${fn} =~ .*\.so\..* ]] || return 1
658
659 until [[ ${fn##*.} == so ]]; do
660 fn="${fn%.*}"
661 [[ -L ${fn} && $(readlink -f "${fn}") == ${orig} ]] && links+=" ${fn}"
662 done
663
0b706743 664 echo "${links}"
a10a1416
665}
666
3198f171
VL
667# find a binary. If we were not passed the full path directly,
668# search in the usual places to find the binary.
6b25d71a 669find_binary() {
81c6e7fb 670 if [[ -z ${1##/*} ]]; then
86bf239e 671 if [[ -x $1 ]] || { strstr "$1" ".so" && ldd $1 &>/dev/null; }; then
81c6e7fb
HH
672 echo $1
673 return 0
674 fi
675 fi
1610a566 676
e29d0b8b 677 type -P $1
3359c8da 678}
36b24d7c 679
62073c30
CG
680# attempt to install any programs specified in a udev rule
681inst_rule_programs() {
682 local _prog _bin
683
684 if grep -qE 'PROGRAM==?"[^ "]+' "$1"; then
685 for _prog in $(grep -E 'PROGRAM==?"[^ "]+' "$1" | sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/'); do
604d1eb2
HH
686 if [ -x ${udevdir}/$_prog ]; then
687 _bin=${udevdir}/$_prog
688 else
689 _bin=$(find_binary "$_prog") || {
690 dinfo "Skipping program $_prog using in udev rule $(basename $1) as it cannot be found"
691 continue;
692 }
693 fi
694
695 #dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)"
696 dracut_install "$_bin"
697 done
698 fi
699 if grep -qE 'RUN==?"[^ "]+' "$1"; then
700 for _prog in $(grep -E 'RUN==?"[^ "]+' "$1" | sed -r 's/.*RUN==?"([^ "]+).*/\1/'); do
701 if [ -x ${udevdir}/$_prog ]; then
702 _bin=${udevdir}/$_prog
703 else
704 _bin=$(find_binary "$_prog") || {
705 dinfo "Skipping program $_prog using in udev rule $(basename $1) as it cannot be found"
706 continue;
707 }
708 fi
709
710 #dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)"
711 dracut_install "$_bin"
712 done
713 fi
714 if grep -qE 'PROGRAM==?"[^ "]+' "$1"; then
715 for _prog in $(grep -E 'IMPORT==?"[^ "]+' "$1" | sed -r 's/.*IMPORT==?"([^ "]+).*/\1/'); do
716 if [ -x ${udevdir}/$_prog ]; then
717 _bin=${udevdir}/$_prog
62073c30
CG
718 else
719 _bin=$(find_binary "$_prog") || {
720 dinfo "Skipping program $_prog using in udev rule $(basename $1) as it cannot be found"
721 continue;
722 }
723 fi
724
725 #dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)"
726 dracut_install "$_bin"
727 done
728 fi
729}
730
f04dc5f3
VL
731# udev rules always get installed in the same place, so
732# create a function to install them to make life simpler.
0b706743 733inst_rules() {
29b10e65 734 local _target=/etc/udev/rules.d _rule _found
fd2312e0 735
604d1eb2 736 inst_dir "${udevdir}/rules.d"
29b10e65
HH
737 inst_dir "$_target"
738 for _rule in "$@"; do
08769b7f 739 if [ "${rule#/}" = "$rule" ]; then
604d1eb2 740 for r in ${udevdir}/rules.d /etc/udev/rules.d; do
76f5fa54
HH
741 if [[ -f $r/$_rule ]]; then
742 _found="$r/$_rule"
62073c30 743 inst_rule_programs "$_found"
604d1eb2 744 inst_simple "$_found"
76f5fa54
HH
745 fi
746 done
747 fi
c97e1a76 748 for r in '' ./ $dracutbasedir/rules.d/; do
29b10e65
HH
749 if [[ -f ${r}$_rule ]]; then
750 _found="${r}$_rule"
62073c30 751 inst_rule_programs "$_found"
604d1eb2 752 inst_simple "$_found" "$_target/${_found##*/}"
c97e1a76
HH
753 fi
754 done
29b10e65 755 [[ $_found ]] || dinfo "Skipping udev rule: $_rule"
f04dc5f3
VL
756 done
757}
758
53f95456
VL
759# install function specialized for hooks
760# $1 = type of hook, $2 = hook priority (lower runs first), $3 = hook
761# All hooks should be POSIX/SuS compliant, they will be sourced by init.
762inst_hook() {
cdad82fd 763 if ! [[ -f $3 ]]; then
e27770e1
764 dfatal "Cannot install a hook ($3) that does not exist."
765 dfatal "Aborting initrd creation."
cc02093d 766 exit 1
cdad82fd 767 elif ! strstr "$hookdirs" "$1"; then
3b403b32 768 dfatal "No such hook type $1. Aborting initrd creation."
cc02093d 769 exit 1
cdad82fd 770 fi
0b53ca70 771 inst_simple "$3" "/lib/dracut/hooks/${1}/${2}${3##*/}"
53f95456
VL
772}
773
3378a54f
774# install any of listed files
775#
776# If first argument is '-d' and second some destination path, first accessible
777# source is installed into this path, otherwise it will installed in the same
778# path as source. If none of listed files was installed, function return 1.
779# On first successful installation it returns with 0 status.
780#
781# Example:
782#
783# inst_any -d /bin/foo /bin/bar /bin/baz
784#
785# Lets assume that /bin/baz exists, so it will be installed as /bin/foo in
786# initramfs.
787inst_any() {
788 local to f
789
790 [[ $1 = '-d' ]] && to="$2" && shift 2
791
792 for f in "$@"; do
793 if [[ -e $f ]]; then
794 [[ $to ]] && inst "$f" "$to" && return 0
795 inst "$f" && return 0
796 fi
797 done
798
799 return 1
800}
801
c9143a63
JAH
802
803# inst_libdir_file [-n <pattern>] <file> [<file>...]
804# Install a <file> located on a lib directory to the initramfs image
cacaa90c 805# -n <pattern> install matching files
c9143a63 806inst_libdir_file() {
0c6565c8 807 local _files
c9143a63 808 if [[ "$1" == "-n" ]]; then
cacaa90c 809 local _pattern=$2
c9143a63
JAH
810 shift 2
811 for _dir in $libdirs; do
7828692f 812 for _i in "$@"; do
c9143a63 813 for _f in "$_dir"/$_i; do
7828692f 814 [[ "$_f" =~ $_pattern ]] || continue
0c6565c8 815 [[ -e "$_f" ]] && _files+="$_f "
c9143a63
JAH
816 done
817 done
818 done
819 else
820 for _dir in $libdirs; do
7828692f 821 for _i in "$@"; do
c9143a63 822 for _f in "$_dir"/$_i; do
0c6565c8 823 [[ -e "$_f" ]] && _files+="$_f "
c9143a63
JAH
824 done
825 done
826 done
827 fi
0c6565c8 828 [[ $_files ]] && dracut_install $_files
c9143a63
JAH
829}
830
831
87122afc
832# install function decompressing the target and handling symlinks
833# $@ = list of compressed (gz or bz2) files or symlinks pointing to such files
834#
835# Function install targets in the same paths inside overlay but decompressed
836# and without extensions (.gz, .bz2).
837inst_decompress() {
b19c5d51 838 local _src _cmd
87122afc 839
29b10e65 840 for _src in $@
87122afc 841 do
29b10e65
HH
842 case ${_src} in
843 *.gz) _cmd='gzip -d' ;;
844 *.bz2) _cmd='bzip2 -d' ;;
87122afc
845 *) return 1 ;;
846 esac
b19c5d51 847 inst_simple ${_src}
87122afc
848 # Decompress with chosen tool. We assume that tool changes name e.g.
849 # from 'name.gz' to 'name'.
29b10e65 850 ${_cmd} "${initdir}${_src}"
87122afc
851 done
852}
853
854# It's similar to above, but if file is not compressed, performs standard
855# install.
856# $@ = list of files
857inst_opt_decompress() {
29b10e65 858 local _src
87122afc 859
29b10e65 860 for _src in $@
87122afc 861 do
29b10e65 862 inst_decompress "${_src}" || inst "${_src}"
87122afc
863 done
864}
865
7e2bca48
HH
866# module_check <dracut module>
867# execute the check() function of module-setup.sh of <dracut module>
868# or the "check" script, if module-setup.sh is not found
869# "check $hostonly" is called
95d2dabc 870module_check() {
29b10e65
HH
871 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
872 local _ret
31f1c02d
AW
873 local _forced=0
874 local _hostonly=$hostonly
875 [ $# -eq 2 ] && _forced=$2
29b10e65
HH
876 [[ -d $_moddir ]] || return 1
877 if [[ ! -f $_moddir/module-setup.sh ]]; then
95d2dabc 878 # if we do not have a check script, we are unconditionally included
29b10e65 879 [[ -x $_moddir/check ]] || return 0
31f1c02d 880 [ $_forced -ne 0 ] && unset hostonly
29b10e65 881 $_moddir/check $hostonly
31f1c02d 882 _ret=$?
95d2dabc
HH
883 else
884 unset check depends install installkernel
29b10e65 885 . $_moddir/module-setup.sh
95d2dabc 886 is_func check || return 0
31f1c02d
AW
887 [ $_forced -ne 0 ] && unset hostonly
888 check $hostonly
29b10e65 889 _ret=$?
95d2dabc 890 unset check depends install installkernel
0c2e3d12 891 fi
31f1c02d
AW
892 hostonly=$_hostonly
893 return $_ret
0c2e3d12
VL
894}
895
7e2bca48
HH
896# module_check_mount <dracut module>
897# execute the check() function of module-setup.sh of <dracut module>
898# or the "check" script, if module-setup.sh is not found
899# "mount_needs=1 check 0" is called
900module_check_mount() {
901 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
902 local _ret
903 mount_needs=1
904 [[ -d $_moddir ]] || return 1
905 if [[ ! -f $_moddir/module-setup.sh ]]; then
906 # if we do not have a check script, we are unconditionally included
907 [[ -x $_moddir/check ]] || return 0
908 mount_needs=1 $_moddir/check 0
909 _ret=$?
910 else
911 unset check depends install installkernel
912 . $_moddir/module-setup.sh
913 is_func check || return 1
914 check 0
915 _ret=$?
916 unset check depends install installkernel
917 fi
918 unset mount_needs
919 return $_ret
920}
921
922# module_depends <dracut module>
923# execute the depends() function of module-setup.sh of <dracut module>
924# or the "depends" script, if module-setup.sh is not found
95d2dabc 925module_depends() {
29b10e65
HH
926 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
927 local _ret
928 [[ -d $_moddir ]] || return 1
929 if [[ ! -f $_moddir/module-setup.sh ]]; then
95d2dabc 930 # if we do not have a check script, we have no deps
29b10e65
HH
931 [[ -x $_moddir/check ]] || return 0
932 $_moddir/check -d
95d2dabc
HH
933 return $?
934 else
935 unset check depends install installkernel
29b10e65 936 . $_moddir/module-setup.sh
95d2dabc
HH
937 is_func depends || return 0
938 depends
29b10e65 939 _ret=$?
95d2dabc 940 unset check depends install installkernel
29b10e65 941 return $_ret
33ee031c 942 fi
0c2e3d12
VL
943}
944
7e2bca48
HH
945# module_install <dracut module>
946# execute the install() function of module-setup.sh of <dracut module>
947# or the "install" script, if module-setup.sh is not found
95d2dabc 948module_install() {
29b10e65
HH
949 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
950 local _ret
951 [[ -d $_moddir ]] || return 1
952 if [[ ! -f $_moddir/module-setup.sh ]]; then
953 [[ -x $_moddir/install ]] && . "$_moddir/install"
95d2dabc
HH
954 return $?
955 else
956 unset check depends install installkernel
29b10e65 957 . $_moddir/module-setup.sh
95d2dabc
HH
958 is_func install || return 0
959 install
29b10e65 960 _ret=$?
95d2dabc 961 unset check depends install installkernel
29b10e65 962 return $_ret
95d2dabc
HH
963 fi
964}
965
7e2bca48
HH
966# module_installkernel <dracut module>
967# execute the installkernel() function of module-setup.sh of <dracut module>
968# or the "installkernel" script, if module-setup.sh is not found
95d2dabc 969module_installkernel() {
29b10e65
HH
970 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
971 local _ret
972 [[ -d $_moddir ]] || return 1
973 if [[ ! -f $_moddir/module-setup.sh ]]; then
974 [[ -x $_moddir/installkernel ]] && . "$_moddir/installkernel"
95d2dabc
HH
975 return $?
976 else
977 unset check depends install installkernel
29b10e65 978 . $_moddir/module-setup.sh
95d2dabc
HH
979 is_func installkernel || return 0
980 installkernel
29b10e65 981 _ret=$?
95d2dabc 982 unset check depends install installkernel
29b10e65 983 return $_ret
95d2dabc
HH
984 fi
985}
986
7e2bca48
HH
987# check_mount <dracut module>
988# check_mount checks, if a dracut module is needed for the given
989# device and filesystem types in "${host_fs_types[@]}"
1b7fd0fa
AW
990check_mount() {
991 local _mod=$1
992 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
993 local _ret
994 local _moddep
995 # If we are already scheduled to be loaded, no need to check again.
996 strstr " $mods_to_load " " $_mod " && return 0
997 strstr " $mods_checked_as_dep " " $_mod " && return 1
998
999 # This should never happen, but...
1000 [[ -d $_moddir ]] || return 1
1001
1002 [[ $2 ]] || mods_checked_as_dep+=" $_mod "
1003
1004 strstr " $omit_dracutmodules " " $_mod " && return 1
1005
1006 if [ "${#host_fs_types[*]}" -gt 0 ]; then
1007 module_check_mount $_mod || return 1
1008 else
1009 # skip this module
1010 return 1
1011 fi
1012
1013 for _moddep in $(module_depends $_mod); do
1014 # handle deps as if they were manually added
1015 strstr " $add_dracutmodules " " $_moddep " || \
1016 add_dracutmodules+=" $_moddep "
1017 strstr " $force_add_dracutmodules " " $_moddep " || \
1018 force_add_dracutmodules+=" $_moddep "
1019 # if a module we depend on fail, fail also
1020 check_module $_moddep || return 1
1021 done
1022
1023 strstr " $mods_to_load " " $_mod " || \
1024 mods_to_load+=" $_mod "
1025
1026 return 0
1027}
1028
7e2bca48
HH
1029# check_module <dracut module> [<use_as_dep>]
1030# check if a dracut module is to be used in the initramfs process
1031# if <use_as_dep> is set, then the process also keeps track
1032# that the modules were checked for the dependency tracking process
95d2dabc 1033check_module() {
29b10e65
HH
1034 local _mod=$1
1035 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
1036 local _ret
1037 local _moddep
95d2dabc 1038 # If we are already scheduled to be loaded, no need to check again.
29b10e65
HH
1039 strstr " $mods_to_load " " $_mod " && return 0
1040 strstr " $mods_checked_as_dep " " $_mod " && return 1
95d2dabc
HH
1041
1042 # This should never happen, but...
29b10e65 1043 [[ -d $_moddir ]] || return 1
95d2dabc 1044
29b10e65 1045 [[ $2 ]] || mods_checked_as_dep+=" $_mod "
95d2dabc 1046
29b10e65 1047 strstr " $omit_dracutmodules " " $_mod " && return 1
95d2dabc 1048
31f1c02d
AW
1049 if strstr " $dracutmodules $add_dracutmodules $force_add_dracutmodules" " $_mod "; then
1050 if strstr " $force_add_dracutmodules" " $_mod"; then
1051 module_check $_mod 1; ret=$?
1052 else
1053 module_check $_mod 0; ret=$?
1054 fi
95d2dabc
HH
1055 # explicit module, so also accept ret=255
1056 [[ $ret = 0 || $ret = 255 ]] || return 1
1057 else
1058 # module not in our list
1059 if [[ $dracutmodules = all ]]; then
1060 # check, if we can and should install this module
29b10e65 1061 module_check $_mod || return 1
cc02093d 1062 else
95d2dabc
HH
1063 # skip this module
1064 return 1
970e646b 1065 fi
95d2dabc 1066 fi
bb764545 1067
29b10e65 1068 for _moddep in $(module_depends $_mod); do
95d2dabc 1069 # handle deps as if they were manually added
29b10e65
HH
1070 strstr " $add_dracutmodules " " $_moddep " || \
1071 add_dracutmodules+=" $_moddep "
31f1c02d
AW
1072 strstr " $force_add_dracutmodules " " $_moddep " || \
1073 force_add_dracutmodules+=" $_moddep "
95d2dabc 1074 # if a module we depend on fail, fail also
29b10e65 1075 check_module $_moddep || return 1
0c2e3d12 1076 done
70503db4 1077
29b10e65
HH
1078 strstr " $mods_to_load " " $_mod " || \
1079 mods_to_load+=" $_mod "
95d2dabc
HH
1080
1081 return 0
1082}
1083
7e2bca48
HH
1084# for_each_module_dir <func>
1085# execute "<func> <dracut module> 1"
1b7fd0fa 1086for_each_module_dir() {
29b10e65
HH
1087 local _modcheck
1088 local _mod
1089 local _moddir
1b7fd0fa
AW
1090 local _func
1091 _func=$1
29b10e65
HH
1092 for _moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
1093 _mod=${_moddir##*/}; _mod=${_mod#[0-9][0-9]}
1b7fd0fa 1094 $_func $_mod 1
70503db4 1095 done
724b87a6
HH
1096
1097 # Report any missing dracut modules, the user has specified
31f1c02d 1098 _modcheck="$add_dracutmodules $force_add_dracutmodules"
29b10e65
HH
1099 [[ $dracutmodules != all ]] && _modcheck="$m $dracutmodules"
1100 for _mod in $_modcheck; do
1101 strstr "$mods_to_load" "$_mod" && continue
1102 strstr "$omit_dracutmodules" "$_mod" && continue
89d44e72 1103 derror "Dracut module \"$_mod\" cannot be found or installed."
724b87a6 1104 done
0c2e3d12
VL
1105}
1106
ddfd1d10
VL
1107# Install a single kernel module along with any firmware it may require.
1108# $1 = full path to kernel module to install
1109install_kmod_with_fw() {
0b440844 1110 # no need to go further if the module is already installed
379c34d2 1111
0b706743
1112 [[ -e "${initdir}/lib/modules/$kernel/${1##*/lib/modules/$kernel/}" ]] \
1113 && return 0
fcbcb252 1114
d8aeb3a7
HH
1115 if [[ -e "$initdir/.kernelmodseen/${1##*/}" ]]; then
1116 read ret < "$initdir/.kernelmodseen/${1##*/}"
1117 return $ret
1118 fi
379c34d2 1119
fcbcb252
HH
1120 if [[ $omit_drivers ]]; then
1121 local _kmod=${1##*/}
1122 _kmod=${_kmod%.ko}
1123 _kmod=${_kmod/-/_}
34248c92
HH
1124 if [[ "$_kmod" =~ $omit_drivers ]]; then
1125 dinfo "Omitting driver $_kmod"
7abd4264 1126 return 0
34248c92
HH
1127 fi
1128 if [[ "${1##*/lib/modules/$kernel/}" =~ $omit_drivers ]]; then
fcbcb252 1129 dinfo "Omitting driver $_kmod"
7abd4264 1130 return 0
fcbcb252
HH
1131 fi
1132 fi
1133
d8aeb3a7
HH
1134 inst_simple "$1" "/lib/modules/$kernel/${1##*/lib/modules/$kernel/}"
1135 ret=$?
6a2c23d1 1136 [ -d "$initdir/.kernelmodseen" ] && \
d8aeb3a7
HH
1137 echo $ret > "$initdir/.kernelmodseen/${1##*/}"
1138 (($ret != 0)) && return $ret
e6024e00
JR
1139
1140 local _modname=${1##*/} _fwdir _found _fw
1141 _modname=${_modname%.ko*}
29b10e65
HH
1142 for _fw in $(modinfo -k $kernel -F firmware $1 2>/dev/null); do
1143 _found=''
1144 for _fwdir in $fw_dir; do
1145 if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then
1146 inst_simple "$_fwdir/$_fw" "/lib/firmware/$_fw"
1147 _found=yes
cc02093d
HH
1148 fi
1149 done
29b10e65 1150 if [[ $_found != yes ]]; then
fe1484f3 1151 if ! [[ -d $(echo /sys/module/${_modname//-/_}|{ read a b; echo $a; }) ]]; then
29b10e65
HH
1152 dinfo "Possible missing firmware \"${_fw}\" for kernel module" \
1153 "\"${_modname}.ko\""
e2cdb570 1154 else
29b10e65
HH
1155 dwarn "Possible missing firmware \"${_fw}\" for kernel module" \
1156 "\"${_modname}.ko\""
e2cdb570 1157 fi
cc02093d 1158 fi
ddfd1d10 1159 done
0b440844 1160 return 0
ddfd1d10
VL
1161}
1162
1163# Do something with all the dependencies of a kernel module.
1164# Note that kernel modules depend on themselves using the technique we use
0b706743
1165# $1 = function to call for each dependency we find
1166# It will be passed the full path to the found kernel module
ddfd1d10
VL
1167# $2 = module to get dependencies for
1168# rest of args = arguments to modprobe
c32bda6b 1169# _fderr specifies FD passed from surrounding scope
ddfd1d10 1170for_each_kmod_dep() {
7abd4264 1171 local _func=$1 _kmod=$2 _cmd _modpath _options
ddfd1d10 1172 shift 2
c32bda6b 1173 modprobe "$@" --ignore-install --show-depends $_kmod 2>&${_fderr} | (
29b10e65
HH
1174 while read _cmd _modpath _options; do
1175 [[ $_cmd = insmod ]] || continue
1176 $_func ${_modpath} || exit $?
0b706743 1177 done
0b706743 1178 )
ddfd1d10
VL
1179}
1180
70c6b773 1181dracut_kernel_post() {
d8aeb3a7
HH
1182 local _moddirname=${srcmods%%/lib/modules/*}
1183
89d44e72
HH
1184 if [[ -f "$initdir/.kernelmodseen/lazylist" ]]; then
1185 xargs modprobe -a ${_moddirname+-d ${_moddirname}/} --ignore-install --show-depends \
1186 < "$initdir/.kernelmodseen/lazylist" 2>/dev/null \
1187 | sort -u \
1188 | while read _cmd _modpath _options; do
1189 [[ $_cmd = insmod ]] || continue
1190 echo "$_modpath"
1191 done > "$initdir/.kernelmodseen/lazylist.dep"
d8aeb3a7 1192
89d44e72
HH
1193 (
1194 if [[ -x /usr/bin/dracut-install ]] && [[ -z $_moddirname ]]; then
1195 xargs dracut-install ${initdir+-D "$initdir"} -a < "$initdir/.kernelmodseen/lazylist.dep"
1196 else
1197 while read _modpath; do
1198 local _destpath=$_modpath
1199 [[ $_moddirname ]] && _destpath=${_destpath##$_moddirname/}
1200 _destpath=${_destpath##*/lib/modules/$kernel/}
1201 inst_simple "$_modpath" "/lib/modules/$kernel/${_destpath}" || exit $?
1202 done < "$initdir/.kernelmodseen/lazylist.dep"
1203 fi
1204 ) &
d8aeb3a7 1205
d8aeb3a7 1206
89d44e72
HH
1207 if [[ -x /usr/bin/dracut-install ]]; then
1208 xargs modinfo -k $kernel -F firmware < "$initdir/.kernelmodseen/lazylist.dep" \
1209 | while read line; do
1210 for _fwdir in $fw_dir; do
1211 echo $_fwdir/$line;
1212 done;
1213 done |xargs dracut-install ${initdir+-D "$initdir"} -a -o
1214 else
1215 for _fw in $(xargs modinfo -k $kernel -F firmware < "$initdir/.kernelmodseen/lazylist.dep"); do
1216 for _fwdir in $fw_dir; do
1217 if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then
1218 inst_simple "$_fwdir/$_fw" "/lib/firmware/$_fw"
1219 break
1220 fi
1221 done
1222 done
1223 fi
d8aeb3a7 1224
89d44e72
HH
1225 wait
1226 fi
70c6b773
HH
1227
1228 for _f in modules.builtin.bin modules.builtin; do
1229 [[ $srcmods/$_f ]] && break
1230 done || {
1231 dfatal "No modules.builtin.bin and modules.builtin found!"
1232 return 1
1233 }
1234
1235 for _f in modules.builtin.bin modules.builtin modules.order; do
1236 [[ $srcmods/$_f ]] && inst_simple "$srcmods/$_f" "/lib/modules/$kernel/$_f"
1237 done
1238
1239 # generate module dependencies for the initrd
1240 if [[ -d $initdir/lib/modules/$kernel ]] && \
1241 ! depmod -a -b "$initdir" $kernel; then
1242 dfatal "\"depmod -a $kernel\" failed."
1243 exit 1
1244 fi
1245
1246 rm -fr "$initdir/.kernelmodseen"
d8aeb3a7 1247}
fe1484f3 1248
881eda69 1249find_kernel_modules_by_path () (
74405477 1250 local _OLDIFS
881eda69 1251 if ! [[ $hostonly ]]; then
74405477
HH
1252 _OLDIFS=$IFS
1253 IFS=:
fe1484f3 1254 while read a rest; do
d8aeb3a7 1255 [[ $a = kernel*/$1/* ]] || continue
74405477 1256 echo $srcmods/$a
fe1484f3 1257 done < $srcmods/modules.dep
74405477 1258 IFS=$_OLDIFS
881eda69 1259 else
fe1484f3 1260 ( cd /sys/module; echo *; ) \
881eda69
JR
1261 | xargs modinfo -F filename -k $kernel 2>/dev/null
1262 fi
74405477 1263 return 0
881eda69 1264)
4073c815 1265
881eda69
JR
1266find_kernel_modules () {
1267 find_kernel_modules_by_path drivers
1268}
1269
a6d3be9d
AW
1270# instmods [-c] <kernel module> [<kernel module> ... ]
1271# instmods [-c] <kernel subsystem>
ddfd1d10 1272# install kernel modules along with all their dependencies.
7e2bca48 1273# <kernel subsystem> can be e.g. "=block" or "=drivers/usb/storage"
6fa0c3d6 1274instmods() {
0c1a8ebc 1275 [[ $no_kernel = yes ]] && return
c32bda6b
MS
1276 # called [sub]functions inherit _fderr
1277 local _fderr=9
a6d3be9d
AW
1278 local _check=no
1279 if [[ $1 = '-c' ]]; then
1280 _check=yes
1281 shift
1282 fi
881eda69
JR
1283
1284 function inst1mod() {
a6d3be9d 1285 local _ret=0 _mod="$1"
29b10e65 1286 case $_mod in
0b706743 1287 =*)
d8aeb3a7
HH
1288 ( [[ "$_mpargs" ]] && echo $_mpargs
1289 find_kernel_modules_by_path "${_mod#=}" ) \
1290 | instmods
1291 ((_ret+=$?))
cc02093d 1292 ;;
0024702f 1293 --*) _mpargs+=" $_mod" ;;
7abd4264 1294 i2o_scsi) return 0;; # Do not load this diagnostic-only module
34248c92 1295 *)
379c34d2 1296 _mod=${_mod##*/}
6568d86a 1297 # if we are already installed, skip this module and go on
cc02093d 1298 # to the next one.
d8aeb3a7
HH
1299 if [[ -f "$initdir/.kernelmodseen/${_mod%.ko}.ko" ]]; then
1300 read _ret <"$initdir/.kernelmodseen/${_mod%.ko}.ko"
1301 return $_ret
1302 fi
881eda69 1303
34248c92
HH
1304 if [[ $omit_drivers ]] && [[ "$1" =~ $omit_drivers ]]; then
1305 dinfo "Omitting driver ${_mod##$srcmods}"
7abd4264 1306 return 0
34248c92 1307 fi
cc02093d
HH
1308 # If we are building a host-specific initramfs and this
1309 # module is not already loaded, move on to the next one.
fe1484f3
HH
1310 [[ $hostonly ]] \
1311 && ! [[ -d $(echo /sys/module/${_mod//-/_}|{ read a b; echo $a; }) ]] \
1312 && ! [[ "$add_drivers" =~ " ${_mod} " ]] \
7abd4264 1313 && return 0
04b56f3a 1314
89d44e72 1315 if [[ "$_check" = "yes" ]] || ! [[ $DRACUT_KERNEL_LAZY ]]; then
d8aeb3a7
HH
1316 # We use '-d' option in modprobe only if modules prefix path
1317 # differs from default '/'. This allows us to use Dracut with
1318 # old version of modprobe which doesn't have '-d' option.
1319 local _moddirname=${srcmods%%/lib/modules/*}
1320 [[ -n ${_moddirname} ]] && _moddirname="-d ${_moddirname}/"
1321
1322 # ok, load the module, all its dependencies, and any firmware
1323 # it may require
1324 for_each_kmod_dep install_kmod_with_fw $_mod \
1325 --set-version $kernel ${_moddirname} $_mpargs
1326 ((_ret+=$?))
1327 else
1328 echo $_mod >> "$initdir/.kernelmodseen/lazylist"
1329 fi
cc02093d 1330 ;;
0b706743 1331 esac
a6d3be9d 1332 return $_ret
881eda69
JR
1333 }
1334
f9708da2 1335 function instmods_1() {
a6d3be9d 1336 local _mod _mpargs
f9708da2
JR
1337 if (($# == 0)); then # filenames from stdin
1338 while read _mod; do
a6d3be9d
AW
1339 inst1mod "${_mod%.ko*}" || {
1340 if [ "$_check" = "yes" ]; then
1341 dfatal "Failed to install $_mod"
1342 return 1
1343 fi
1344 }
f9708da2
JR
1345 done
1346 fi
1347 while (($# > 0)); do # filenames as arguments
a6d3be9d
AW
1348 inst1mod ${1%.ko*} || {
1349 if [ "$_check" = "yes" ]; then
1350 dfatal "Failed to install $1"
1351 return 1
1352 fi
1353 }
f9708da2 1354 shift
881eda69 1355 done
a6d3be9d 1356 return 0
f9708da2
JR
1357 }
1358
a6d3be9d 1359 local _ret _filter_not_found='FATAL: Module .* not found.'
c32bda6b
MS
1360 # Capture all stderr from modprobe to _fderr. We could use {var}>...
1361 # redirections, but that would make dracut require bash4 at least.
1362 eval "( instmods_1 \"\$@\" ) ${_fderr}>&1" \
86191581 1363 | while read line; do [[ "$line" =~ $_filter_not_found ]] || echo $line;done | derror
a6d3be9d 1364 _ret=$?
a6d3be9d 1365 return $_ret
0b706743 1366}