]>
Commit | Line | Data |
---|---|---|
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 | # |
258de828 | 22 | export LC_MESSAGES=C |
f4031e8a HH |
23 | |
24 | if [[ $DRACUT_KERNEL_LAZY ]] && ! [[ $DRACUT_KERNEL_LAZY_HASHDIR ]]; then | |
25 | if ! [[ -d "$initdir/.kernelmodseen" ]]; then | |
26 | mkdir -p "$initdir/.kernelmodseen" | |
27 | fi | |
28 | DRACUT_KERNEL_LAZY_HASHDIR="$initdir/.kernelmodseen" | |
29 | fi | |
ec1aa3bc | 30 | |
eaa924b6 HH |
31 | if [[ $initdir ]] && ! [[ -d $initdir ]]; then |
32 | mkdir -p "$initdir" | |
33 | fi | |
34 | ||
8d95b8b3 | 35 | # Generic substring function. If $2 is in $1, return 0. |
2c19a5fa CF |
36 | strstr() { [[ $1 = *"$2"* ]]; } |
37 | # Generic glob matching function. If glob pattern $2 matches anywhere in $1, OK | |
38 | strglobin() { [[ $1 = *$2* ]]; } | |
39 | # Generic glob matching function. If glob pattern $2 matches all of $1, OK | |
40 | strglob() { [[ $1 = $2 ]]; } | |
8d95b8b3 | 41 | |
30e6e809 HH |
42 | # helper function for check() in module-setup.sh |
43 | # to check for required installed binaries | |
44 | # issues a standardized warning message | |
45 | require_binaries() { | |
46 | local _module_name="${moddir##*/}" | |
47 | local _ret=0 | |
48 | ||
49 | if [[ "$1" = "-m" ]]; then | |
50 | _module_name="$2" | |
51 | shift 2 | |
52 | fi | |
53 | ||
54 | for cmd in "$@"; do | |
55 | if ! find_binary "$cmd" &>/dev/null; then | |
0fa5dbed | 56 | dinfo "dracut module '${_module_name#[0-9][0-9]}' will not be installed, because command '$cmd' could not be found!" |
30e6e809 HH |
57 | ((_ret++)) |
58 | fi | |
59 | done | |
60 | return $_ret | |
61 | } | |
62 | ||
63 | require_any_binary() { | |
64 | local _module_name="${moddir##*/}" | |
65 | local _ret=1 | |
66 | ||
67 | if [[ "$1" = "-m" ]]; then | |
68 | _module_name="$2" | |
69 | shift 2 | |
70 | fi | |
71 | ||
72 | for cmd in "$@"; do | |
73 | if find_binary "$cmd" &>/dev/null; then | |
74 | _ret=0 | |
75 | break | |
76 | fi | |
77 | done | |
78 | ||
79 | if (( $_ret != 0 )); then | |
83a3cba7 | 80 | dinfo "$_module_name: Could not find any command of '$@'!" |
30e6e809 HH |
81 | return 1 |
82 | fi | |
83 | ||
84 | return 0 | |
85 | } | |
86 | ||
f4031e8a HH |
87 | # find a binary. If we were not passed the full path directly, |
88 | # search in the usual places to find the binary. | |
89 | find_binary() { | |
90 | if [[ -z ${1##/*} ]]; then | |
b093aa2d HH |
91 | if [[ -x $1 ]] || { [[ "$1" == *.so* ]] && ldd "$1" &>/dev/null; }; then |
92 | printf "%s\n" "$1" | |
f4031e8a HH |
93 | return 0 |
94 | fi | |
95 | fi | |
96 | ||
b093aa2d | 97 | type -P "${1##*/}" |
f4031e8a HH |
98 | } |
99 | ||
0874654c HH |
100 | if ! [[ $dracutbasedir ]]; then |
101 | dracutbasedir=${BASH_SOURCE[0]%/*} | |
102 | [[ $dracutbasedir = "dracut-functions" ]] && dracutbasedir="." | |
103 | [[ $dracutbasedir ]] || dracutbasedir="." | |
104 | dracutbasedir="$(readlink -f $dracutbasedir)" | |
105 | fi | |
106 | ||
4fe1bdd4 HH |
107 | ldconfig_paths() |
108 | { | |
109 | local a i | |
110 | declare -A a | |
111 | for i in $( | |
5ea0be0a HH |
112 | ldconfig -pN 2>/dev/null | grep -F '=>' | grep -E -v '/(lib|lib64|usr/lib|usr/lib64)/[^/]*$' | while read a b c d; do |
113 | d=${d%/*} | |
114 | printf "%s\n" "$d"; | |
4fe1bdd4 HH |
115 | done |
116 | ); do | |
117 | a["$i"]=1; | |
118 | done; | |
119 | printf "%s\n" ${!a[@]} | |
120 | } | |
121 | ||
8d95b8b3 HH |
122 | # Detect lib paths |
123 | if ! [[ $libdirs ]] ; then | |
b093aa2d | 124 | if [[ "$(ldd /bin/sh)" == */lib64/* ]] &>/dev/null \ |
8d95b8b3 HH |
125 | && [[ -d /lib64 ]]; then |
126 | libdirs+=" /lib64" | |
127 | [[ -d /usr/lib64 ]] && libdirs+=" /usr/lib64" | |
128 | else | |
129 | libdirs+=" /lib" | |
130 | [[ -d /usr/lib ]] && libdirs+=" /usr/lib" | |
131 | fi | |
4fe1bdd4 | 132 | |
1d50dfe6 | 133 | libdirs+=" $(ldconfig_paths)" |
4fe1bdd4 | 134 | |
8d95b8b3 HH |
135 | export libdirs |
136 | fi | |
137 | ||
138 | if ! [[ $kernel ]]; then | |
139 | kernel=$(uname -r) | |
140 | export kernel | |
141 | fi | |
142 | ||
f06c2b58 HH |
143 | # Version comparision function. Assumes Linux style version scheme. |
144 | # $1 = version a | |
145 | # $2 = comparision op (gt, ge, eq, le, lt, ne) | |
146 | # $3 = version b | |
147 | vercmp() { | |
148 | local _n1=(${1//./ }) _op=$2 _n2=(${3//./ }) _i _res | |
149 | ||
150 | for ((_i=0; ; _i++)) | |
151 | do | |
152 | if [[ ! ${_n1[_i]}${_n2[_i]} ]]; then _res=0 | |
153 | elif ((${_n1[_i]:-0} > ${_n2[_i]:-0})); then _res=1 | |
154 | elif ((${_n1[_i]:-0} < ${_n2[_i]:-0})); then _res=2 | |
155 | else continue | |
156 | fi | |
157 | break | |
158 | done | |
159 | ||
160 | case $_op in | |
161 | gt) ((_res == 1));; | |
162 | ge) ((_res != 2));; | |
163 | eq) ((_res == 0));; | |
164 | le) ((_res != 1));; | |
165 | lt) ((_res == 2));; | |
166 | ne) ((_res != 0));; | |
167 | esac | |
168 | } | |
169 | ||
8d95b8b3 | 170 | srcmods="/lib/modules/$kernel/" |
f06c2b58 | 171 | |
8d95b8b3 | 172 | [[ $drivers_dir ]] && { |
f06c2b58 | 173 | if ! command -v kmod &>/dev/null && vercmp "$(modprobe --version | cut -d' ' -f3)" lt 3.7; then |
8d95b8b3 HH |
174 | dfatal 'To use --kmoddir option module-init-tools >= 3.7 is required.' |
175 | exit 1 | |
176 | fi | |
177 | srcmods="$drivers_dir" | |
178 | } | |
179 | export srcmods | |
180 | ||
d6d53f60 | 181 | if ! type dinfo >/dev/null 2>&1; then |
552ecca6 | 182 | . "$dracutbasedir/dracut-logger.sh" |
e103615b AŻ |
183 | dlog_init |
184 | fi | |
185 | ||
593b315c HH |
186 | if ! [[ $initdir ]]; then |
187 | dfatal "initdir not set" | |
188 | exit 1 | |
189 | fi | |
190 | ||
7e2bca48 HH |
191 | # export standard hookdirs |
192 | [[ $hookdirs ]] || { | |
4fed3ddf | 193 | hookdirs="cmdline pre-udev pre-trigger netroot " |
6e3cc00f | 194 | hookdirs+="initqueue initqueue/settled initqueue/online initqueue/finished initqueue/timeout " |
eef7649e | 195 | hookdirs+="pre-mount pre-pivot cleanup mount " |
2b6dd6a1 | 196 | hookdirs+="emergency shutdown-emergency pre-shutdown shutdown " |
7e2bca48 HH |
197 | export hookdirs |
198 | } | |
199 | ||
8d85429a HH |
200 | dracut_need_initqueue() { |
201 | >"$initdir/lib/dracut/need-initqueue" | |
202 | } | |
203 | ||
204 | dracut_module_included() { | |
50411d30 | 205 | [[ " $mods_to_load $modules_loaded " == *\ $*\ * ]] |
8d85429a HH |
206 | } |
207 | ||
87122afc AŻ |
208 | # Create all subdirectories for given path without creating the last element. |
209 | # $1 = path | |
b093aa2d HH |
210 | mksubdirs() { |
211 | [[ -e ${1%/*} ]] || mkdir -m 0755 -p -- "${1%/*}" | |
212 | } | |
87122afc | 213 | |
7e2bca48 HH |
214 | # is_func <command> |
215 | # Check whether $1 is a function. | |
95d2dabc | 216 | is_func() { |
b093aa2d | 217 | [[ "$(type -t "$1")" = "function" ]] |
95d2dabc HH |
218 | } |
219 | ||
87122afc AŻ |
220 | # Function prints global variables in format name=value line by line. |
221 | # $@ = list of global variables' name | |
222 | print_vars() { | |
29b10e65 | 223 | local _var _value |
87122afc | 224 | |
b093aa2d | 225 | for _var in "$@" |
87122afc | 226 | do |
7a94a432 | 227 | eval printf -v _value "%s" \""\$$_var"\" |
b093aa2d | 228 | [[ ${_value} ]] && printf '%s="%s"\n' "$_var" "$_value" |
87122afc AŻ |
229 | done |
230 | } | |
231 | ||
7e2bca48 HH |
232 | # normalize_path <path> |
233 | # Prints the normalized path, where it removes any duplicated | |
234 | # and trailing slashes. | |
235 | # Example: | |
236 | # $ normalize_path ///test/test// | |
237 | # /test/test | |
626d9eba | 238 | normalize_path() { |
c44e3cb4 MS |
239 | shopt -q -s extglob |
240 | set -- "${1//+(\/)//}" | |
241 | shopt -q -u extglob | |
466a5998 | 242 | printf "%s\n" "${1%/}" |
626d9eba | 243 | } |
d4bb4316 | 244 | |
7e2bca48 HH |
245 | # convert_abs_rel <from> <to> |
246 | # Prints the relative path, when creating a symlink to <to> from <from>. | |
247 | # Example: | |
248 | # $ convert_abs_rel /usr/bin/test /bin/test-2 | |
249 | # ../../bin/test-2 | |
250 | # $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test | |
d4bb4316 | 251 | convert_abs_rel() { |
6d2a7942 | 252 | local __current __absolute __abssize __cursize __newpath |
c44e3cb4 | 253 | local -i __i __level |
d4bb4316 | 254 | |
c44e3cb4 MS |
255 | set -- "$(normalize_path "$1")" "$(normalize_path "$2")" |
256 | ||
c1609dd4 | 257 | # corner case #1 - self looping link |
466a5998 | 258 | [[ "$1" == "$2" ]] && { printf "%s\n" "${1##*/}"; return; } |
c1609dd4 MS |
259 | |
260 | # corner case #2 - own dir link | |
466a5998 | 261 | [[ "${1%/*}" == "$2" ]] && { printf ".\n"; return; } |
c1609dd4 | 262 | |
6d2a7942 HH |
263 | IFS="/" __current=($1) |
264 | IFS="/" __absolute=($2) | |
d4bb4316 HH |
265 | |
266 | __abssize=${#__absolute[@]} | |
267 | __cursize=${#__current[@]} | |
268 | ||
b093aa2d | 269 | while [[ "${__absolute[__level]}" == "${__current[__level]}" ]] |
d4bb4316 HH |
270 | do |
271 | (( __level++ )) | |
272 | if (( __level > __abssize || __level > __cursize )) | |
273 | then | |
274 | break | |
275 | fi | |
276 | done | |
277 | ||
278 | for ((__i = __level; __i < __cursize-1; __i++)) | |
279 | do | |
280 | if ((__i > __level)) | |
281 | then | |
282 | __newpath=$__newpath"/" | |
283 | fi | |
284 | __newpath=$__newpath".." | |
285 | done | |
286 | ||
287 | for ((__i = __level; __i < __abssize; __i++)) | |
288 | do | |
289 | if [[ -n $__newpath ]] | |
290 | then | |
291 | __newpath=$__newpath"/" | |
292 | fi | |
293 | __newpath=$__newpath${__absolute[__i]} | |
294 | done | |
295 | ||
466a5998 | 296 | printf "%s\n" "$__newpath" |
d4bb4316 HH |
297 | } |
298 | ||
b093aa2d | 299 | if [[ "$(ln --help)" == *--relative* ]]; then |
a20d24de HH |
300 | ln_r() { |
301 | ln -sfnr "${initdir}/$1" "${initdir}/$2" | |
302 | } | |
303 | else | |
304 | ln_r() { | |
305 | local _source=$1 | |
306 | local _dest=$2 | |
307 | [[ -d "${_dest%/*}" ]] && _dest=$(readlink -f "${_dest%/*}")/${_dest##*/} | |
b093aa2d | 308 | ln -sfn -- "$(convert_abs_rel "${_dest}" "${_source}")" "${initdir}/${_dest}" |
a20d24de HH |
309 | } |
310 | fi | |
311 | ||
7e2bca48 | 312 | # get_fs_env <device> |
97af51db | 313 | # Get and the ID_FS_TYPE variable from udev for a device. |
7e2bca48 | 314 | # Example: |
97af51db | 315 | # $ get_fs_env /dev/sda2 |
7e2bca48 | 316 | # ext4 |
9ede1929 | 317 | get_fs_env() { |
0e979d48 HH |
318 | local evalstr |
319 | local found | |
320 | ||
7c179686 | 321 | [[ $1 ]] || return |
29b10e65 | 322 | unset ID_FS_TYPE |
69f7ed96 HH |
323 | ID_FS_TYPE=$(blkid -u filesystem -o export -- "$1" \ |
324 | | while read line; do | |
325 | if [[ "$line" == TYPE\=* ]]; then | |
326 | printf "%s" "${line#TYPE=}"; | |
327 | exit 0; | |
328 | fi | |
329 | done) | |
330 | if [[ $ID_FS_TYPE ]]; then | |
331 | printf "%s" "$ID_FS_TYPE" | |
332 | return 0 | |
7c179686 | 333 | fi |
a5cde2dd HH |
334 | return 1 |
335 | } | |
9ede1929 | 336 | |
7e2bca48 HH |
337 | # get_maj_min <device> |
338 | # Prints the major and minor of a device node. | |
339 | # Example: | |
340 | # $ get_maj_min /dev/sda2 | |
341 | # 8:2 | |
480d772f | 342 | get_maj_min() { |
dba20559 HH |
343 | local _maj _min _majmin |
344 | _majmin="$(stat -L -c '%t:%T' "$1" 2>/dev/null)" | |
345 | printf "%s" "$((0x${_majmin%:*})):$((0x${_majmin#*:}))" | |
480d772f HH |
346 | } |
347 | ||
281327f7 HH |
348 | |
349 | # get_devpath_block <device> | |
350 | # get the DEVPATH in /sys of a block device | |
351 | get_devpath_block() { | |
8552a327 | 352 | local _majmin _i |
281327f7 HH |
353 | _majmin=$(get_maj_min "$1") |
354 | ||
355 | for _i in /sys/block/*/dev /sys/block/*/*/dev; do | |
356 | [[ -e "$_i" ]] || continue | |
357 | if [[ "$_majmin" == "$(<"$_i")" ]]; then | |
358 | printf "%s" "${_i%/dev}" | |
359 | return 0 | |
360 | fi | |
361 | done | |
362 | return 1 | |
363 | } | |
364 | ||
69f7ed96 HH |
365 | # get a persistent path from a device |
366 | get_persistent_dev() { | |
367 | local i _tmp _dev | |
368 | ||
369 | _dev=$(get_maj_min "$1") | |
370 | [ -z "$_dev" ] && return | |
371 | ||
324ea606 HH |
372 | for i in \ |
373 | /dev/mapper/* \ | |
3411ad66 | 374 | /dev/disk/${persistent_policy:-by-uuid}/* \ |
324ea606 HH |
375 | /dev/disk/by-uuid/* \ |
376 | /dev/disk/by-label/* \ | |
377 | /dev/disk/by-partuuid/* \ | |
378 | /dev/disk/by-partlabel/* \ | |
379 | /dev/disk/by-id/* \ | |
380 | /dev/disk/by-path/* \ | |
381 | ; do | |
2b9d8f65 | 382 | [[ -e "$i" ]] || continue |
1743473b | 383 | [[ $i == /dev/mapper/control ]] && continue |
69f7ed96 HH |
384 | [[ $i == /dev/mapper/mpath* ]] && continue |
385 | _tmp=$(get_maj_min "$i") | |
386 | if [ "$_tmp" = "$_dev" ]; then | |
387 | printf -- "%s" "$i" | |
388 | return | |
389 | fi | |
390 | done | |
9efb74a3 | 391 | printf -- "%s" "$1" |
69f7ed96 HH |
392 | } |
393 | ||
c82a1133 HH |
394 | expand_persistent_dev() { |
395 | local _dev=$1 | |
396 | ||
397 | case "$_dev" in | |
398 | LABEL=*) | |
399 | _dev="/dev/disk/by-label/${_dev#LABEL=}" | |
400 | ;; | |
401 | UUID=*) | |
402 | _dev="${_dev#UUID=}" | |
93b02f50 | 403 | _dev="${_dev,,}" |
c82a1133 HH |
404 | _dev="/dev/disk/by-uuid/${_dev}" |
405 | ;; | |
406 | PARTUUID=*) | |
407 | _dev="${_dev#PARTUUID=}" | |
93b02f50 | 408 | _dev="${_dev,,}" |
c82a1133 HH |
409 | _dev="/dev/disk/by-partuuid/${_dev}" |
410 | ;; | |
411 | PARTLABEL=*) | |
412 | _dev="/dev/disk/by-partlabel/${_dev#PARTLABEL=}" | |
413 | ;; | |
414 | esac | |
415 | printf "%s" "$_dev" | |
416 | } | |
417 | ||
324ea606 | 418 | shorten_persistent_dev() { |
c82a1133 HH |
419 | local _dev="$1" |
420 | case "$_dev" in | |
324ea606 | 421 | /dev/disk/by-uuid/*) |
c82a1133 | 422 | printf "%s" "UUID=${_dev##*/}";; |
324ea606 | 423 | /dev/disk/by-label/*) |
c82a1133 | 424 | printf "%s" "LABEL=${_dev##*/}";; |
324ea606 | 425 | /dev/disk/by-partuuid/*) |
c82a1133 | 426 | printf "%s" "PARTUUID=${_dev##*/}";; |
324ea606 | 427 | /dev/disk/by-partlabel/*) |
c82a1133 | 428 | printf "%s" "PARTLABEL=${_dev##*/}";; |
324ea606 | 429 | *) |
c82a1133 | 430 | printf "%s" "$_dev";; |
324ea606 HH |
431 | esac |
432 | } | |
433 | ||
7e2bca48 HH |
434 | # find_block_device <mountpoint> |
435 | # Prints the major and minor number of the block device | |
436 | # for a given mountpoint. | |
437 | # Unless $use_fstab is set to "yes" the functions | |
438 | # uses /proc/self/mountinfo as the primary source of the | |
439 | # information and only falls back to /etc/fstab, if the mountpoint | |
440 | # is not found there. | |
441 | # Example: | |
442 | # $ find_block_device /usr | |
443 | # 8:4 | |
f76ef3aa | 444 | find_block_device() { |
9d36d4fb | 445 | local _majmin _dev _majmin _find_mpt |
c8d685c9 | 446 | _find_mpt="$1" |
0b706743 | 447 | if [[ $use_fstab != yes ]]; then |
9d36d4fb | 448 | [[ -d $_find_mpt/. ]] |
dba20559 HH |
449 | findmnt -e -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" | { \ |
450 | while read _majmin _dev; do | |
451 | if [[ -b $_dev ]]; then | |
452 | if ! [[ $_majmin ]] || [[ $_majmin == 0:* ]]; then | |
453 | _majmin=$(get_maj_min $_dev) | |
454 | fi | |
455 | if [[ $_majmin ]]; then | |
466a5998 | 456 | printf "%s\n" "$_majmin" |
dba20559 | 457 | else |
466a5998 | 458 | printf "%s\n" "$_dev" |
dba20559 HH |
459 | fi |
460 | return 0 | |
461 | fi | |
462 | if [[ $_dev = *:* ]]; then | |
466a5998 | 463 | printf "%s\n" "$_dev" |
dba20559 HH |
464 | return 0 |
465 | fi | |
466 | done; return 1; } && return 0 | |
467 | fi | |
468 | # fall back to /etc/fstab | |
469 | ||
470 | findmnt -e --fstab -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" | { \ | |
9d36d4fb | 471 | while read _majmin _dev; do |
dba20559 HH |
472 | if ! [[ $_dev ]]; then |
473 | _dev="$_majmin" | |
474 | unset _majmin | |
475 | fi | |
9d36d4fb | 476 | if [[ -b $_dev ]]; then |
dba20559 | 477 | [[ $_majmin ]] || _majmin=$(get_maj_min $_dev) |
9d36d4fb | 478 | if [[ $_majmin ]]; then |
466a5998 | 479 | printf "%s\n" "$_majmin" |
9d36d4fb | 480 | else |
466a5998 | 481 | printf "%s\n" "$_dev" |
9d36d4fb HH |
482 | fi |
483 | return 0 | |
484 | fi | |
485 | if [[ $_dev = *:* ]]; then | |
466a5998 | 486 | printf "%s\n" "$_dev" |
9d36d4fb | 487 | return 0 |
cc02093d | 488 | fi |
dba20559 | 489 | done; return 1; } && return 0 |
0b706743 AŻ |
490 | |
491 | return 1 | |
17829e94 VL |
492 | } |
493 | ||
9d36d4fb HH |
494 | # find_mp_fstype <mountpoint> |
495 | # Echo the filesystem type for a given mountpoint. | |
7e2bca48 HH |
496 | # /proc/self/mountinfo is taken as the primary source of information |
497 | # and /etc/fstab is used as a fallback. | |
498 | # No newline is appended! | |
499 | # Example: | |
9d36d4fb | 500 | # $ find_mp_fstype /;echo |
7e2bca48 | 501 | # ext4 |
9d36d4fb HH |
502 | find_mp_fstype() { |
503 | local _fs | |
7ae5d9d1 | 504 | |
9d36d4fb | 505 | if [[ $use_fstab != yes ]]; then |
dba20559 HH |
506 | findmnt -e -v -n -o 'FSTYPE' --target "$1" | { \ |
507 | while read _fs; do | |
508 | [[ $_fs ]] || continue | |
509 | [[ $_fs = "autofs" ]] && continue | |
466a5998 | 510 | printf "%s" "$_fs" |
dba20559 HH |
511 | return 0 |
512 | done; return 1; } && return 0 | |
513 | fi | |
514 | ||
515 | findmnt --fstab -e -v -n -o 'FSTYPE' --target "$1" | { \ | |
9d36d4fb HH |
516 | while read _fs; do |
517 | [[ $_fs ]] || continue | |
518 | [[ $_fs = "autofs" ]] && continue | |
466a5998 | 519 | printf "%s" "$_fs" |
9d36d4fb | 520 | return 0 |
dba20559 | 521 | done; return 1; } && return 0 |
7ae5d9d1 HH |
522 | |
523 | return 1 | |
524 | } | |
525 | ||
9d36d4fb HH |
526 | # find_dev_fstype <device> |
527 | # Echo the filesystem type for a given device. | |
81672479 HH |
528 | # /proc/self/mountinfo is taken as the primary source of information |
529 | # and /etc/fstab is used as a fallback. | |
530 | # No newline is appended! | |
531 | # Example: | |
9d36d4fb | 532 | # $ find_dev_fstype /dev/sda2;echo |
81672479 | 533 | # ext4 |
9d36d4fb | 534 | find_dev_fstype() { |
5e601454 | 535 | local _find_dev _fs |
9d36d4fb | 536 | _find_dev="$1" |
a4f7b504 HH |
537 | if ! [[ "$_find_dev" = /dev* ]]; then |
538 | [[ -b "/dev/block/$_find_dev" ]] && _find_dev="/dev/block/$_find_dev" | |
539 | fi | |
5e601454 HH |
540 | |
541 | if [[ $use_fstab != yes ]]; then | |
dba20559 HH |
542 | findmnt -e -v -n -o 'FSTYPE' --source "$_find_dev" | { \ |
543 | while read _fs; do | |
544 | [[ $_fs ]] || continue | |
545 | [[ $_fs = "autofs" ]] && continue | |
466a5998 | 546 | printf "%s" "$_fs" |
dba20559 HH |
547 | return 0 |
548 | done; return 1; } && return 0 | |
549 | fi | |
550 | ||
551 | findmnt --fstab -e -v -n -o 'FSTYPE' --source "$_find_dev" | { \ | |
5e601454 HH |
552 | while read _fs; do |
553 | [[ $_fs ]] || continue | |
554 | [[ $_fs = "autofs" ]] && continue | |
466a5998 | 555 | printf "%s" "$_fs" |
5e601454 | 556 | return 0 |
dba20559 | 557 | done; return 1; } && return 0 |
5e601454 HH |
558 | |
559 | return 1 | |
97af51db | 560 | } |
5e601454 | 561 | |
bbc9bfe1 HH |
562 | # find_mp_fsopts <mountpoint> |
563 | # Echo the filesystem options for a given mountpoint. | |
564 | # /proc/self/mountinfo is taken as the primary source of information | |
565 | # and /etc/fstab is used as a fallback. | |
566 | # No newline is appended! | |
567 | # Example: | |
568 | # $ find_mp_fsopts /;echo | |
569 | # rw,relatime,discard,data=ordered | |
570 | find_mp_fsopts() { | |
571 | if [[ $use_fstab != yes ]]; then | |
572 | findmnt -e -v -n -o 'OPTIONS' --target "$1" 2>/dev/null && return 0 | |
573 | fi | |
574 | ||
575 | findmnt --fstab -e -v -n -o 'OPTIONS' --target "$1" | |
576 | } | |
577 | ||
97af51db HH |
578 | # find_dev_fsopts <device> |
579 | # Echo the filesystem options for a given device. | |
580 | # /proc/self/mountinfo is taken as the primary source of information | |
581 | # and /etc/fstab is used as a fallback. | |
582 | # Example: | |
583 | # $ find_dev_fsopts /dev/sda2 | |
584 | # rw,relatime,discard,data=ordered | |
585 | find_dev_fsopts() { | |
586 | local _find_dev _opts | |
587 | _find_dev="$1" | |
588 | if ! [[ "$_find_dev" = /dev* ]]; then | |
589 | [[ -b "/dev/block/$_find_dev" ]] && _find_dev="/dev/block/$_find_dev" | |
590 | fi | |
591 | ||
592 | if [[ $use_fstab != yes ]]; then | |
593 | findmnt -e -v -n -o 'OPTIONS' --source "$_find_dev" 2>/dev/null && return 0 | |
594 | fi | |
595 | ||
596 | findmnt --fstab -e -v -n -o 'OPTIONS' --source "$_find_dev" | |
81672479 HH |
597 | } |
598 | ||
97af51db | 599 | |
7ae5d9d1 | 600 | # finds the major:minor of the block device backing the root filesystem. |
f76ef3aa VL |
601 | find_root_block_device() { find_block_device /; } |
602 | ||
7e2bca48 | 603 | # for_each_host_dev_fs <func> |
d351541e | 604 | # Execute "<func> <dev> <filesystem>" for every "<dev> <fs>" pair found |
7e2bca48 | 605 | # in ${host_fs_types[@]} |
480d772f HH |
606 | for_each_host_dev_fs() |
607 | { | |
608 | local _func="$1" | |
d0096de7 | 609 | local _dev |
2efa546f | 610 | local _ret=1 |
fd191a7b HH |
611 | |
612 | [[ "${!host_fs_types[@]}" ]] || return 0 | |
613 | ||
d351541e HH |
614 | for _dev in "${!host_fs_types[@]}"; do |
615 | $_func "$_dev" "${host_fs_types[$_dev]}" && _ret=0 | |
480d772f | 616 | done |
2efa546f | 617 | return $_ret |
480d772f HH |
618 | } |
619 | ||
fd191a7b HH |
620 | host_fs_all() |
621 | { | |
466a5998 | 622 | printf "%s\n" "${host_fs_types[@]}" |
fd191a7b HH |
623 | } |
624 | ||
17829e94 VL |
625 | # Walk all the slave relationships for a given block device. |
626 | # Stop when our helper function returns success | |
627 | # $1 = function to call on every found block device | |
628 | # $2 = block device in major:minor format | |
0b706743 | 629 | check_block_and_slaves() { |
29b10e65 | 630 | local _x |
17829e94 | 631 | [[ -b /dev/block/$2 ]] || return 1 # Not a block device? So sorry. |
96c6f6f3 | 632 | if ! lvm_internal_dev $2; then "$1" $2 && return; fi |
533d7dc4 | 633 | check_vol_slaves "$@" && return 0 |
3478b314 | 634 | if [[ -f /sys/dev/block/$2/../dev ]]; then |
dba20559 | 635 | check_block_and_slaves $1 $(<"/sys/dev/block/$2/../dev") && return 0 |
a3afcf2a | 636 | fi |
17829e94 | 637 | [[ -d /sys/dev/block/$2/slaves ]] || return 1 |
29b10e65 | 638 | for _x in /sys/dev/block/$2/slaves/*/dev; do |
d82e0d7d | 639 | [[ -f $_x ]] || continue |
dba20559 | 640 | check_block_and_slaves $1 $(<"$_x") && return 0 |
17829e94 VL |
641 | done |
642 | return 1 | |
643 | } | |
644 | ||
83e0dc7a DY |
645 | check_block_and_slaves_all() { |
646 | local _x _ret=1 | |
647 | [[ -b /dev/block/$2 ]] || return 1 # Not a block device? So sorry. | |
96c6f6f3 | 648 | if ! lvm_internal_dev $2 && "$1" $2; then |
dba20559 | 649 | _ret=0 |
83e0dc7a DY |
650 | fi |
651 | check_vol_slaves "$@" && return 0 | |
652 | if [[ -f /sys/dev/block/$2/../dev ]]; then | |
dba20559 | 653 | check_block_and_slaves_all $1 $(<"/sys/dev/block/$2/../dev") && _ret=0 |
83e0dc7a DY |
654 | fi |
655 | [[ -d /sys/dev/block/$2/slaves ]] || return 1 | |
656 | for _x in /sys/dev/block/$2/slaves/*/dev; do | |
657 | [[ -f $_x ]] || continue | |
dba20559 | 658 | check_block_and_slaves_all $1 $(<"$_x") && _ret=0 |
83e0dc7a DY |
659 | done |
660 | return $_ret | |
661 | } | |
662 | # for_each_host_dev_and_slaves <func> | |
663 | # Execute "<func> <dev>" for every "<dev>" found | |
664 | # in ${host_devs[@]} and their slaves | |
665 | for_each_host_dev_and_slaves_all() | |
666 | { | |
667 | local _func="$1" | |
668 | local _dev | |
669 | local _ret=1 | |
fd191a7b HH |
670 | |
671 | [[ "${host_devs[@]}" ]] || return 0 | |
672 | ||
83e0dc7a DY |
673 | for _dev in ${host_devs[@]}; do |
674 | [[ -b "$_dev" ]] || continue | |
83e0dc7a | 675 | if check_block_and_slaves_all $_func $(get_maj_min $_dev); then |
dba20559 | 676 | _ret=0 |
83e0dc7a DY |
677 | fi |
678 | done | |
679 | return $_ret | |
680 | } | |
681 | ||
682 | for_each_host_dev_and_slaves() | |
683 | { | |
684 | local _func="$1" | |
685 | local _dev | |
fd191a7b HH |
686 | |
687 | [[ "${host_devs[@]}" ]] || return 0 | |
688 | ||
83e0dc7a DY |
689 | for _dev in ${host_devs[@]}; do |
690 | [[ -b "$_dev" ]] || continue | |
a999414e | 691 | check_block_and_slaves $_func $(get_maj_min $_dev) && return 0 |
83e0dc7a DY |
692 | done |
693 | return 1 | |
694 | } | |
695 | ||
533d7dc4 HH |
696 | # ugly workaround for the lvm design |
697 | # There is no volume group device, | |
698 | # so, there are no slave devices for volume groups. | |
699 | # Logical volumes only have the slave devices they really live on, | |
700 | # but you cannot create the logical volume without the volume group. | |
95bde758 | 701 | # And the volume group might be bigger than the devices the LV needs. |
533d7dc4 | 702 | check_vol_slaves() { |
29b10e65 | 703 | local _lv _vg _pv |
0b706743 | 704 | for i in /dev/mapper/*; do |
1743473b | 705 | [[ $i == /dev/mapper/control ]] && continue |
c4e48eae | 706 | _lv=$(get_maj_min $i) |
29b10e65 HH |
707 | if [[ $_lv = $2 ]]; then |
708 | _vg=$(lvm lvs --noheadings -o vg_name $i 2>/dev/null) | |
cc02093d | 709 | # strip space |
466a5998 | 710 | _vg=$(printf "%s\n" "$_vg") |
29b10e65 HH |
711 | if [[ $_vg ]]; then |
712 | for _pv in $(lvm vgs --noheadings -o pv_name "$_vg" 2>/dev/null) | |
0b706743 | 713 | do |
c4e48eae | 714 | check_block_and_slaves $1 $(get_maj_min $_pv) && return 0 |
cc02093d HH |
715 | done |
716 | fi | |
717 | fi | |
533d7dc4 HH |
718 | done |
719 | return 1 | |
720 | } | |
721 | ||
8aa99268 HH |
722 | # fs_get_option <filesystem options> <search for option> |
723 | # search for a specific option in a bunch of filesystem options | |
724 | # and return the value | |
725 | fs_get_option() { | |
726 | local _fsopts=$1 | |
727 | local _option=$2 | |
728 | local OLDIFS="$IFS" | |
729 | IFS=, | |
730 | set -- $_fsopts | |
731 | IFS="$OLDIFS" | |
732 | while [ $# -gt 0 ]; do | |
733 | case $1 in | |
734 | $_option=*) | |
735 | echo ${1#${_option}=} | |
736 | break | |
737 | esac | |
738 | shift | |
739 | done | |
740 | } | |
741 | ||
89d44e72 | 742 | |
55a0b3ab HH |
743 | if ! [[ $DRACUT_INSTALL ]]; then |
744 | DRACUT_INSTALL=$(find_binary dracut-install) | |
745 | fi | |
19612483 | 746 | |
55a0b3ab HH |
747 | if ! [[ $DRACUT_INSTALL ]] && [[ -x $dracutbasedir/dracut-install ]]; then |
748 | DRACUT_INSTALL=$dracutbasedir/dracut-install | |
749 | fi | |
3f590c78 | 750 | |
55a0b3ab HH |
751 | if ! [[ -x $DRACUT_INSTALL ]]; then |
752 | dfatal "dracut-install not found!" | |
753 | exit 10 | |
754 | fi | |
22048b44 | 755 | |
55a0b3ab HH |
756 | [[ $DRACUT_RESOLVE_LAZY ]] || export DRACUT_RESOLVE_DEPS=1 |
757 | inst_dir() { | |
758 | [[ -e ${initdir}/"$1" ]] && return 0 # already there | |
ffc68f35 HH |
759 | $DRACUT_INSTALL ${initdir:+-D "$initdir"} -d "$@" |
760 | (($? != 0)) && derror $DRACUT_INSTALL ${initdir:+-D "$initdir"} -d "$@" || : | |
55a0b3ab | 761 | } |
22048b44 | 762 | |
55a0b3ab | 763 | inst() { |
4ef45f13 HH |
764 | local _hostonly_install |
765 | if [[ "$1" == "-H" ]]; then | |
766 | _hostonly_install="-H" | |
767 | shift | |
768 | fi | |
55a0b3ab | 769 | [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there |
4ef45f13 HH |
770 | $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@" |
771 | (($? != 0)) && derror $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@" || : | |
55a0b3ab | 772 | } |
89d44e72 | 773 | |
55a0b3ab | 774 | inst_simple() { |
4ef45f13 HH |
775 | local _hostonly_install |
776 | if [[ "$1" == "-H" ]]; then | |
777 | _hostonly_install="-H" | |
778 | shift | |
779 | fi | |
55a0b3ab HH |
780 | [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there |
781 | [[ -e $1 ]] || return 1 # no source | |
4ef45f13 HH |
782 | $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${_hostonly_install:+-H} "$@" |
783 | (($? != 0)) && derror $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${_hostonly_install:+-H} "$@" || : | |
55a0b3ab | 784 | } |
89d44e72 | 785 | |
55a0b3ab | 786 | inst_symlink() { |
4ef45f13 HH |
787 | local _hostonly_install |
788 | if [[ "$1" == "-H" ]]; then | |
789 | _hostonly_install="-H" | |
790 | shift | |
791 | fi | |
55a0b3ab HH |
792 | [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there |
793 | [[ -L $1 ]] || return 1 | |
4ef45f13 HH |
794 | $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@" |
795 | (($? != 0)) && derror $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@" || : | |
55a0b3ab | 796 | } |
89d44e72 | 797 | |
af119460 | 798 | inst_multiple() { |
4ef45f13 | 799 | local _ret |
26cd262a | 800 | $DRACUT_INSTALL ${initdir:+-D "$initdir"} -a ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$@" |
4ef45f13 HH |
801 | _ret=$? |
802 | (($_ret != 0)) && derror $DRACUT_INSTALL ${initdir:+-D "$initdir"} -a ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@" || : | |
803 | return $_ret | |
55a0b3ab | 804 | } |
89d44e72 | 805 | |
af119460 HH |
806 | dracut_install() { |
807 | inst_multiple "$@" | |
808 | } | |
809 | ||
55a0b3ab | 810 | inst_library() { |
4ef45f13 HH |
811 | local _hostonly_install |
812 | if [[ "$1" == "-H" ]]; then | |
813 | _hostonly_install="-H" | |
814 | shift | |
815 | fi | |
55a0b3ab HH |
816 | [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there |
817 | [[ -e $1 ]] || return 1 # no source | |
4ef45f13 HH |
818 | $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@" |
819 | (($? != 0)) && derror $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} ${_hostonly_install:+-H} "$@" || : | |
55a0b3ab | 820 | } |
89d44e72 | 821 | |
55a0b3ab | 822 | inst_binary() { |
26cd262a HH |
823 | $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$@" |
824 | (($? != 0)) && derror $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$@" || : | |
55a0b3ab | 825 | } |
89d44e72 | 826 | |
55a0b3ab | 827 | inst_script() { |
26cd262a HH |
828 | $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$@" |
829 | (($? != 0)) && derror $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${DRACUT_RESOLVE_DEPS:+-l} ${DRACUT_FIPS_MODE:+-f} "$@" || : | |
830 | } | |
831 | ||
832 | mark_hostonly() { | |
833 | for i in "$@"; do | |
834 | echo "$i" >> "$initdir/lib/dracut/hostonly-files" | |
835 | done | |
55a0b3ab | 836 | } |
36b24d7c | 837 | |
a10a1416 AŻ |
838 | # find symlinks linked to given library file |
839 | # $1 = library file | |
840 | # Function searches for symlinks by stripping version numbers appended to | |
841 | # library filename, checks if it points to the same target and finally | |
842 | # prints the list of symlinks to stdout. | |
843 | # | |
844 | # Example: | |
845 | # rev_lib_symlinks libfoo.so.8.1 | |
846 | # output: libfoo.so.8 libfoo.so | |
847 | # (Only if libfoo.so.8 and libfoo.so exists on host system.) | |
848 | rev_lib_symlinks() { | |
849 | [[ ! $1 ]] && return 0 | |
850 | ||
851 | local fn="$1" orig="$(readlink -f "$1")" links='' | |
852 | ||
b093aa2d | 853 | [[ ${fn} == *.so.* ]] || return 1 |
a10a1416 AŻ |
854 | |
855 | until [[ ${fn##*.} == so ]]; do | |
856 | fn="${fn%.*}" | |
857 | [[ -L ${fn} && $(readlink -f "${fn}") == ${orig} ]] && links+=" ${fn}" | |
858 | done | |
859 | ||
0b706743 | 860 | echo "${links}" |
a10a1416 AŻ |
861 | } |
862 | ||
62073c30 CG |
863 | # attempt to install any programs specified in a udev rule |
864 | inst_rule_programs() { | |
865 | local _prog _bin | |
866 | ||
867 | if grep -qE 'PROGRAM==?"[^ "]+' "$1"; then | |
868 | for _prog in $(grep -E 'PROGRAM==?"[^ "]+' "$1" | sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/'); do | |
76d5c79e | 869 | _bin="" |
604d1eb2 HH |
870 | if [ -x ${udevdir}/$_prog ]; then |
871 | _bin=${udevdir}/$_prog | |
34bd2be2 | 872 | elif [[ "${_prog/\$env\{/}" == "$_prog" ]]; then |
604d1eb2 | 873 | _bin=$(find_binary "$_prog") || { |
cc218087 | 874 | dinfo "Skipping program $_prog using in udev rule ${1##*/} as it cannot be found" |
604d1eb2 HH |
875 | continue; |
876 | } | |
877 | fi | |
878 | ||
af119460 | 879 | [[ $_bin ]] && inst_binary "$_bin" |
604d1eb2 HH |
880 | done |
881 | fi | |
da9c5181 HH |
882 | if grep -qE 'RUN[+=]=?"[^ "]+' "$1"; then |
883 | for _prog in $(grep -E 'RUN[+=]=?"[^ "]+' "$1" | sed -r 's/.*RUN[+=]=?"([^ "]+).*/\1/'); do | |
76d5c79e | 884 | _bin="" |
604d1eb2 HH |
885 | if [ -x ${udevdir}/$_prog ]; then |
886 | _bin=${udevdir}/$_prog | |
34bd2be2 | 887 | elif [[ "${_prog/\$env\{/}" == "$_prog" ]] && [[ "${_prog}" != "/sbin/initqueue" ]]; then |
604d1eb2 | 888 | _bin=$(find_binary "$_prog") || { |
cc218087 | 889 | dinfo "Skipping program $_prog using in udev rule ${1##*/} as it cannot be found" |
604d1eb2 HH |
890 | continue; |
891 | } | |
892 | fi | |
893 | ||
af119460 | 894 | [[ $_bin ]] && inst_binary "$_bin" |
604d1eb2 HH |
895 | done |
896 | fi | |
65d1a8a4 HH |
897 | if grep -qE 'IMPORT\{program\}==?"[^ "]+' "$1"; then |
898 | for _prog in $(grep -E 'IMPORT\{program\}==?"[^ "]+' "$1" | sed -r 's/.*IMPORT\{program\}==?"([^ "]+).*/\1/'); do | |
76d5c79e | 899 | _bin="" |
604d1eb2 HH |
900 | if [ -x ${udevdir}/$_prog ]; then |
901 | _bin=${udevdir}/$_prog | |
34bd2be2 | 902 | elif [[ "${_prog/\$env\{/}" == "$_prog" ]]; then |
62073c30 | 903 | _bin=$(find_binary "$_prog") || { |
cc218087 | 904 | dinfo "Skipping program $_prog using in udev rule ${1##*/} as it cannot be found" |
62073c30 CG |
905 | continue; |
906 | } | |
907 | fi | |
908 | ||
76d5c79e | 909 | [[ $_bin ]] && dracut_install "$_bin" |
62073c30 CG |
910 | done |
911 | fi | |
912 | } | |
913 | ||
e0a39336 HH |
914 | # attempt to install any programs specified in a udev rule |
915 | inst_rule_group_owner() { | |
916 | local i | |
917 | ||
918 | if grep -qE 'OWNER=?"[^ "]+' "$1"; then | |
919 | for i in $(grep -E 'OWNER=?"[^ "]+' "$1" | sed -r 's/.*OWNER=?"([^ "]+).*/\1/'); do | |
920 | if ! egrep -q "^$i:" "$initdir/etc/passwd" 2>/dev/null; then | |
921 | egrep "^$i:" /etc/passwd 2>/dev/null >> "$initdir/etc/passwd" | |
922 | fi | |
923 | done | |
924 | fi | |
925 | if grep -qE 'GROUP=?"[^ "]+' "$1"; then | |
926 | for i in $(grep -E 'GROUP=?"[^ "]+' "$1" | sed -r 's/.*GROUP=?"([^ "]+).*/\1/'); do | |
927 | if ! egrep -q "^$i:" "$initdir/etc/group" 2>/dev/null; then | |
928 | egrep "^$i:" /etc/group 2>/dev/null >> "$initdir/etc/group" | |
929 | fi | |
930 | done | |
931 | fi | |
932 | } | |
933 | ||
8d85429a HH |
934 | inst_rule_initqueue() { |
935 | if grep -q -F initqueue "$1"; then | |
936 | dracut_need_initqueue | |
937 | fi | |
938 | } | |
939 | ||
f04dc5f3 VL |
940 | # udev rules always get installed in the same place, so |
941 | # create a function to install them to make life simpler. | |
0b706743 | 942 | inst_rules() { |
29b10e65 | 943 | local _target=/etc/udev/rules.d _rule _found |
fd2312e0 | 944 | |
604d1eb2 | 945 | inst_dir "${udevdir}/rules.d" |
29b10e65 HH |
946 | inst_dir "$_target" |
947 | for _rule in "$@"; do | |
256cba18 | 948 | if [ "${_rule#/}" = "$_rule" ]; then |
ffc68f35 | 949 | for r in ${udevdir}/rules.d ${hostonly:+/etc/udev/rules.d}; do |
ace51ef5 | 950 | if [[ -e $r/$_rule ]]; then |
76f5fa54 | 951 | _found="$r/$_rule" |
62073c30 | 952 | inst_rule_programs "$_found" |
e0a39336 | 953 | inst_rule_group_owner "$_found" |
8d85429a | 954 | inst_rule_initqueue "$_found" |
604d1eb2 | 955 | inst_simple "$_found" |
76f5fa54 HH |
956 | fi |
957 | done | |
958 | fi | |
63330a89 HH |
959 | for r in '' $dracutbasedir/rules.d/; do |
960 | # skip rules without an absolute path | |
961 | [[ "${r}$_rule" != /* ]] && continue | |
962 | ||
29b10e65 HH |
963 | if [[ -f ${r}$_rule ]]; then |
964 | _found="${r}$_rule" | |
62073c30 | 965 | inst_rule_programs "$_found" |
e0a39336 | 966 | inst_rule_group_owner "$_found" |
8d85429a | 967 | inst_rule_initqueue "$_found" |
604d1eb2 | 968 | inst_simple "$_found" "$_target/${_found##*/}" |
c97e1a76 HH |
969 | fi |
970 | done | |
29b10e65 | 971 | [[ $_found ]] || dinfo "Skipping udev rule: $_rule" |
f04dc5f3 VL |
972 | done |
973 | } | |
974 | ||
bfa1db78 HR |
975 | inst_rules_wildcard() { |
976 | local _target=/etc/udev/rules.d _rule _found | |
977 | ||
978 | inst_dir "${udevdir}/rules.d" | |
979 | inst_dir "$_target" | |
980 | for _rule in ${udevdir}/rules.d/$1 ${dracutbasedir}/rules.d/$1 ; do | |
981 | if [[ -e $_rule ]]; then | |
982 | inst_rule_programs "$_rule" | |
983 | inst_rule_group_owner "$_rule" | |
984 | inst_rule_initqueue "$_rule" | |
985 | inst_simple "$_rule" | |
986 | _found=$_rule | |
987 | fi | |
988 | done | |
989 | if [ -n ${hostonly} ] ; then | |
990 | for _rule in ${_target}/$1 ; do | |
991 | if [[ -f $_rule ]]; then | |
992 | inst_rule_programs "$_rule" | |
993 | inst_rule_group_owner "$_rule" | |
994 | inst_rule_initqueue "$_rule" | |
995 | inst_simple "$_rule" | |
996 | _found=$_rule | |
997 | fi | |
998 | done | |
999 | fi | |
1000 | [[ $_found ]] || dinfo "Skipping udev rule: $_rule" | |
1001 | } | |
1002 | ||
c46cda82 HH |
1003 | prepare_udev_rules() { |
1004 | [ -z "$UDEVVERSION" ] && export UDEVVERSION=$(udevadm --version) | |
1005 | ||
1006 | for f in "$@"; do | |
1007 | f="${initdir}/etc/udev/rules.d/$f" | |
1008 | [ -e "$f" ] || continue | |
1009 | while read line; do | |
1010 | if [ "${line%%IMPORT PATH_ID}" != "$line" ]; then | |
1011 | if [ $UDEVVERSION -ge 174 ]; then | |
1012 | printf '%sIMPORT{builtin}="path_id"\n' "${line%%IMPORT PATH_ID}" | |
1013 | else | |
1014 | printf '%sIMPORT{program}="path_id %%p"\n' "${line%%IMPORT PATH_ID}" | |
1015 | fi | |
1016 | elif [ "${line%%IMPORT BLKID}" != "$line" ]; then | |
1017 | if [ $UDEVVERSION -ge 176 ]; then | |
1018 | printf '%sIMPORT{builtin}="blkid"\n' "${line%%IMPORT BLKID}" | |
1019 | else | |
1020 | printf '%sIMPORT{program}="/sbin/blkid -o udev -p $tempnode"\n' "${line%%IMPORT BLKID}" | |
1021 | fi | |
1022 | else | |
1023 | echo "$line" | |
1024 | fi | |
1025 | done < "${f}" > "${f}.new" | |
1026 | mv "${f}.new" "$f" | |
1027 | done | |
1028 | } | |
1029 | ||
53f95456 VL |
1030 | # install function specialized for hooks |
1031 | # $1 = type of hook, $2 = hook priority (lower runs first), $3 = hook | |
1032 | # All hooks should be POSIX/SuS compliant, they will be sourced by init. | |
1033 | inst_hook() { | |
cdad82fd | 1034 | if ! [[ -f $3 ]]; then |
e27770e1 AŻ |
1035 | dfatal "Cannot install a hook ($3) that does not exist." |
1036 | dfatal "Aborting initrd creation." | |
cc02093d | 1037 | exit 1 |
b093aa2d | 1038 | elif ! [[ "$hookdirs" == *$1* ]]; then |
3b403b32 | 1039 | dfatal "No such hook type $1. Aborting initrd creation." |
cc02093d | 1040 | exit 1 |
cdad82fd | 1041 | fi |
5a84ac3f | 1042 | inst_simple "$3" "/lib/dracut/hooks/${1}/${2}-${3##*/}" |
53f95456 VL |
1043 | } |
1044 | ||
3378a54f AŻ |
1045 | # install any of listed files |
1046 | # | |
1047 | # If first argument is '-d' and second some destination path, first accessible | |
1048 | # source is installed into this path, otherwise it will installed in the same | |
1049 | # path as source. If none of listed files was installed, function return 1. | |
1050 | # On first successful installation it returns with 0 status. | |
1051 | # | |
1052 | # Example: | |
1053 | # | |
1054 | # inst_any -d /bin/foo /bin/bar /bin/baz | |
1055 | # | |
1056 | # Lets assume that /bin/baz exists, so it will be installed as /bin/foo in | |
1057 | # initramfs. | |
1058 | inst_any() { | |
1059 | local to f | |
1060 | ||
1061 | [[ $1 = '-d' ]] && to="$2" && shift 2 | |
1062 | ||
1063 | for f in "$@"; do | |
1064 | if [[ -e $f ]]; then | |
1065 | [[ $to ]] && inst "$f" "$to" && return 0 | |
1066 | inst "$f" && return 0 | |
1067 | fi | |
1068 | done | |
1069 | ||
1070 | return 1 | |
1071 | } | |
1072 | ||
c9143a63 JAH |
1073 | |
1074 | # inst_libdir_file [-n <pattern>] <file> [<file>...] | |
1075 | # Install a <file> located on a lib directory to the initramfs image | |
cacaa90c | 1076 | # -n <pattern> install matching files |
c9143a63 | 1077 | inst_libdir_file() { |
0c6565c8 | 1078 | local _files |
c9143a63 | 1079 | if [[ "$1" == "-n" ]]; then |
cacaa90c | 1080 | local _pattern=$2 |
c9143a63 JAH |
1081 | shift 2 |
1082 | for _dir in $libdirs; do | |
7828692f | 1083 | for _i in "$@"; do |
c9143a63 | 1084 | for _f in "$_dir"/$_i; do |
7828692f | 1085 | [[ "$_f" =~ $_pattern ]] || continue |
0c6565c8 | 1086 | [[ -e "$_f" ]] && _files+="$_f " |
c9143a63 JAH |
1087 | done |
1088 | done | |
1089 | done | |
1090 | else | |
1091 | for _dir in $libdirs; do | |
7828692f | 1092 | for _i in "$@"; do |
c9143a63 | 1093 | for _f in "$_dir"/$_i; do |
0c6565c8 | 1094 | [[ -e "$_f" ]] && _files+="$_f " |
c9143a63 JAH |
1095 | done |
1096 | done | |
1097 | done | |
1098 | fi | |
af119460 | 1099 | [[ $_files ]] && inst_multiple $_files |
c9143a63 JAH |
1100 | } |
1101 | ||
1102 | ||
87122afc AŻ |
1103 | # install function decompressing the target and handling symlinks |
1104 | # $@ = list of compressed (gz or bz2) files or symlinks pointing to such files | |
1105 | # | |
1106 | # Function install targets in the same paths inside overlay but decompressed | |
1107 | # and without extensions (.gz, .bz2). | |
1108 | inst_decompress() { | |
b19c5d51 | 1109 | local _src _cmd |
87122afc | 1110 | |
29b10e65 | 1111 | for _src in $@ |
87122afc | 1112 | do |
29b10e65 | 1113 | case ${_src} in |
c62b9461 | 1114 | *.gz) _cmd='gzip -f -d' ;; |
29b10e65 | 1115 | *.bz2) _cmd='bzip2 -d' ;; |
87122afc AŻ |
1116 | *) return 1 ;; |
1117 | esac | |
b19c5d51 | 1118 | inst_simple ${_src} |
87122afc AŻ |
1119 | # Decompress with chosen tool. We assume that tool changes name e.g. |
1120 | # from 'name.gz' to 'name'. | |
29b10e65 | 1121 | ${_cmd} "${initdir}${_src}" |
87122afc AŻ |
1122 | done |
1123 | } | |
1124 | ||
1125 | # It's similar to above, but if file is not compressed, performs standard | |
1126 | # install. | |
1127 | # $@ = list of files | |
1128 | inst_opt_decompress() { | |
29b10e65 | 1129 | local _src |
87122afc | 1130 | |
29b10e65 | 1131 | for _src in $@ |
87122afc | 1132 | do |
29b10e65 | 1133 | inst_decompress "${_src}" || inst "${_src}" |
87122afc AŻ |
1134 | done |
1135 | } | |
1136 | ||
7e2bca48 HH |
1137 | # module_check <dracut module> |
1138 | # execute the check() function of module-setup.sh of <dracut module> | |
1139 | # or the "check" script, if module-setup.sh is not found | |
1140 | # "check $hostonly" is called | |
95d2dabc | 1141 | module_check() { |
29b10e65 HH |
1142 | local _moddir=$(echo ${dracutbasedir}/modules.d/??${1}) |
1143 | local _ret | |
31f1c02d AW |
1144 | local _forced=0 |
1145 | local _hostonly=$hostonly | |
1146 | [ $# -eq 2 ] && _forced=$2 | |
29b10e65 HH |
1147 | [[ -d $_moddir ]] || return 1 |
1148 | if [[ ! -f $_moddir/module-setup.sh ]]; then | |
95d2dabc | 1149 | # if we do not have a check script, we are unconditionally included |
29b10e65 | 1150 | [[ -x $_moddir/check ]] || return 0 |
31f1c02d | 1151 | [ $_forced -ne 0 ] && unset hostonly |
29b10e65 | 1152 | $_moddir/check $hostonly |
31f1c02d | 1153 | _ret=$? |
95d2dabc | 1154 | else |
1743473b | 1155 | unset check depends cmdline install installkernel |
b093aa2d | 1156 | check() { true; } |
29b10e65 | 1157 | . $_moddir/module-setup.sh |
95d2dabc | 1158 | is_func check || return 0 |
31f1c02d | 1159 | [ $_forced -ne 0 ] && unset hostonly |
30e6e809 | 1160 | moddir=$_moddir check $hostonly |
29b10e65 | 1161 | _ret=$? |
1743473b | 1162 | unset check depends cmdline install installkernel |
0c2e3d12 | 1163 | fi |
31f1c02d AW |
1164 | hostonly=$_hostonly |
1165 | return $_ret | |
0c2e3d12 VL |
1166 | } |
1167 | ||
7e2bca48 HH |
1168 | # module_check_mount <dracut module> |
1169 | # execute the check() function of module-setup.sh of <dracut module> | |
1170 | # or the "check" script, if module-setup.sh is not found | |
1171 | # "mount_needs=1 check 0" is called | |
1172 | module_check_mount() { | |
1173 | local _moddir=$(echo ${dracutbasedir}/modules.d/??${1}) | |
1174 | local _ret | |
1175 | mount_needs=1 | |
1176 | [[ -d $_moddir ]] || return 1 | |
1177 | if [[ ! -f $_moddir/module-setup.sh ]]; then | |
1178 | # if we do not have a check script, we are unconditionally included | |
1179 | [[ -x $_moddir/check ]] || return 0 | |
1180 | mount_needs=1 $_moddir/check 0 | |
1181 | _ret=$? | |
1182 | else | |
1743473b | 1183 | unset check depends cmdline install installkernel |
b093aa2d | 1184 | check() { false; } |
7e2bca48 | 1185 | . $_moddir/module-setup.sh |
30e6e809 | 1186 | moddir=$_moddir check 0 |
7e2bca48 | 1187 | _ret=$? |
1743473b | 1188 | unset check depends cmdline install installkernel |
7e2bca48 HH |
1189 | fi |
1190 | unset mount_needs | |
1191 | return $_ret | |
1192 | } | |
1193 | ||
1194 | # module_depends <dracut module> | |
1195 | # execute the depends() function of module-setup.sh of <dracut module> | |
1196 | # or the "depends" script, if module-setup.sh is not found | |
95d2dabc | 1197 | module_depends() { |
29b10e65 HH |
1198 | local _moddir=$(echo ${dracutbasedir}/modules.d/??${1}) |
1199 | local _ret | |
1200 | [[ -d $_moddir ]] || return 1 | |
1201 | if [[ ! -f $_moddir/module-setup.sh ]]; then | |
95d2dabc | 1202 | # if we do not have a check script, we have no deps |
29b10e65 HH |
1203 | [[ -x $_moddir/check ]] || return 0 |
1204 | $_moddir/check -d | |
95d2dabc HH |
1205 | return $? |
1206 | else | |
1743473b | 1207 | unset check depends cmdline install installkernel |
b093aa2d | 1208 | depends() { true; } |
29b10e65 | 1209 | . $_moddir/module-setup.sh |
30e6e809 | 1210 | moddir=$_moddir depends |
29b10e65 | 1211 | _ret=$? |
1743473b HH |
1212 | unset check depends cmdline install installkernel |
1213 | return $_ret | |
1214 | fi | |
1215 | } | |
1216 | ||
1217 | # module_cmdline <dracut module> | |
1218 | # execute the cmdline() function of module-setup.sh of <dracut module> | |
1219 | # or the "cmdline" script, if module-setup.sh is not found | |
1220 | module_cmdline() { | |
1221 | local _moddir=$(echo ${dracutbasedir}/modules.d/??${1}) | |
1222 | local _ret | |
1223 | [[ -d $_moddir ]] || return 1 | |
1224 | if [[ ! -f $_moddir/module-setup.sh ]]; then | |
1225 | [[ -x $_moddir/cmdline ]] && . "$_moddir/cmdline" | |
1226 | return $? | |
1227 | else | |
1228 | unset check depends cmdline install installkernel | |
1229 | cmdline() { true; } | |
1230 | . $_moddir/module-setup.sh | |
30e6e809 | 1231 | moddir=$_moddir cmdline |
1743473b HH |
1232 | _ret=$? |
1233 | unset check depends cmdline install installkernel | |
29b10e65 | 1234 | return $_ret |
33ee031c | 1235 | fi |
0c2e3d12 VL |
1236 | } |
1237 | ||
7e2bca48 HH |
1238 | # module_install <dracut module> |
1239 | # execute the install() function of module-setup.sh of <dracut module> | |
1240 | # or the "install" script, if module-setup.sh is not found | |
95d2dabc | 1241 | module_install() { |
29b10e65 HH |
1242 | local _moddir=$(echo ${dracutbasedir}/modules.d/??${1}) |
1243 | local _ret | |
1244 | [[ -d $_moddir ]] || return 1 | |
1245 | if [[ ! -f $_moddir/module-setup.sh ]]; then | |
1246 | [[ -x $_moddir/install ]] && . "$_moddir/install" | |
95d2dabc HH |
1247 | return $? |
1248 | else | |
1743473b | 1249 | unset check depends cmdline install installkernel |
b093aa2d | 1250 | install() { true; } |
29b10e65 | 1251 | . $_moddir/module-setup.sh |
30e6e809 | 1252 | moddir=$_moddir install |
29b10e65 | 1253 | _ret=$? |
1743473b | 1254 | unset check depends cmdline install installkernel |
29b10e65 | 1255 | return $_ret |
95d2dabc HH |
1256 | fi |
1257 | } | |
1258 | ||
7e2bca48 HH |
1259 | # module_installkernel <dracut module> |
1260 | # execute the installkernel() function of module-setup.sh of <dracut module> | |
1261 | # or the "installkernel" script, if module-setup.sh is not found | |
95d2dabc | 1262 | module_installkernel() { |
29b10e65 HH |
1263 | local _moddir=$(echo ${dracutbasedir}/modules.d/??${1}) |
1264 | local _ret | |
1265 | [[ -d $_moddir ]] || return 1 | |
1266 | if [[ ! -f $_moddir/module-setup.sh ]]; then | |
1267 | [[ -x $_moddir/installkernel ]] && . "$_moddir/installkernel" | |
95d2dabc HH |
1268 | return $? |
1269 | else | |
1743473b | 1270 | unset check depends cmdline install installkernel |
b093aa2d | 1271 | installkernel() { true; } |
dba20559 | 1272 | . $_moddir/module-setup.sh |
30e6e809 | 1273 | moddir=$_moddir installkernel |
29b10e65 | 1274 | _ret=$? |
1743473b | 1275 | unset check depends cmdline install installkernel |
29b10e65 | 1276 | return $_ret |
95d2dabc HH |
1277 | fi |
1278 | } | |
1279 | ||
7e2bca48 HH |
1280 | # check_mount <dracut module> |
1281 | # check_mount checks, if a dracut module is needed for the given | |
1282 | # device and filesystem types in "${host_fs_types[@]}" | |
1b7fd0fa AW |
1283 | check_mount() { |
1284 | local _mod=$1 | |
1285 | local _moddir=$(echo ${dracutbasedir}/modules.d/??${1}) | |
1286 | local _ret | |
1287 | local _moddep | |
ecfa02bd HH |
1288 | |
1289 | [ "${#host_fs_types[*]}" -le 0 ] && return 1 | |
1290 | ||
1b7fd0fa | 1291 | # If we are already scheduled to be loaded, no need to check again. |
b093aa2d HH |
1292 | [[ " $mods_to_load " == *\ $_mod\ * ]] && return 0 |
1293 | [[ " $mods_checked_as_dep " == *\ $_mod\ * ]] && return 1 | |
1b7fd0fa AW |
1294 | |
1295 | # This should never happen, but... | |
1296 | [[ -d $_moddir ]] || return 1 | |
1297 | ||
1298 | [[ $2 ]] || mods_checked_as_dep+=" $_mod " | |
1299 | ||
b093aa2d | 1300 | if [[ " $omit_dracutmodules " == *\ $_mod\ * ]]; then |
0f283709 HH |
1301 | return 1 |
1302 | fi | |
1b7fd0fa | 1303 | |
b093aa2d | 1304 | if [[ " $dracutmodules $add_dracutmodules $force_add_dracutmodules" == *\ $_mod\ * ]]; then |
ecfa02bd HH |
1305 | module_check_mount $_mod; ret=$? |
1306 | ||
1307 | # explicit module, so also accept ret=255 | |
1308 | [[ $ret = 0 || $ret = 255 ]] || return 1 | |
1b7fd0fa | 1309 | else |
ecfa02bd HH |
1310 | # module not in our list |
1311 | if [[ $dracutmodules = all ]]; then | |
1312 | # check, if we can and should install this module | |
1313 | module_check_mount $_mod || return 1 | |
1314 | else | |
1315 | # skip this module | |
1316 | return 1 | |
1317 | fi | |
1b7fd0fa AW |
1318 | fi |
1319 | ||
ecfa02bd | 1320 | |
1b7fd0fa AW |
1321 | for _moddep in $(module_depends $_mod); do |
1322 | # handle deps as if they were manually added | |
b093aa2d | 1323 | [[ " $add_dracutmodules " == *\ $_moddep\ * ]] || \ |
1b7fd0fa | 1324 | add_dracutmodules+=" $_moddep " |
b093aa2d | 1325 | [[ " $force_add_dracutmodules " == *\ $_moddep\ * ]] || \ |
1b7fd0fa AW |
1326 | force_add_dracutmodules+=" $_moddep " |
1327 | # if a module we depend on fail, fail also | |
0f283709 | 1328 | if ! check_module $_moddep; then |
600c8769 | 1329 | derror "dracut module '$_mod' depends on '$_moddep', which can't be installed" |
0f283709 HH |
1330 | return 1 |
1331 | fi | |
1b7fd0fa AW |
1332 | done |
1333 | ||
b093aa2d | 1334 | [[ " $mods_to_load " == *\ $_mod\ * ]] || \ |
1b7fd0fa AW |
1335 | mods_to_load+=" $_mod " |
1336 | ||
1337 | return 0 | |
1338 | } | |
1339 | ||
7e2bca48 HH |
1340 | # check_module <dracut module> [<use_as_dep>] |
1341 | # check if a dracut module is to be used in the initramfs process | |
1342 | # if <use_as_dep> is set, then the process also keeps track | |
1343 | # that the modules were checked for the dependency tracking process | |
95d2dabc | 1344 | check_module() { |
29b10e65 HH |
1345 | local _mod=$1 |
1346 | local _moddir=$(echo ${dracutbasedir}/modules.d/??${1}) | |
1347 | local _ret | |
1348 | local _moddep | |
95d2dabc | 1349 | # If we are already scheduled to be loaded, no need to check again. |
b093aa2d HH |
1350 | [[ " $mods_to_load " == *\ $_mod\ * ]] && return 0 |
1351 | [[ " $mods_checked_as_dep " == *\ $_mod\ * ]] && return 1 | |
95d2dabc HH |
1352 | |
1353 | # This should never happen, but... | |
29b10e65 | 1354 | [[ -d $_moddir ]] || return 1 |
95d2dabc | 1355 | |
29b10e65 | 1356 | [[ $2 ]] || mods_checked_as_dep+=" $_mod " |
95d2dabc | 1357 | |
b093aa2d | 1358 | if [[ " $omit_dracutmodules " == *\ $_mod\ * ]]; then |
600c8769 | 1359 | dinfo "dracut module '$_mod' will not be installed, because it's in the list to be omitted!" |
0f283709 HH |
1360 | return 1 |
1361 | fi | |
95d2dabc | 1362 | |
b093aa2d HH |
1363 | if [[ " $dracutmodules $add_dracutmodules $force_add_dracutmodules" == *\ $_mod\ * ]]; then |
1364 | if [[ " $force_add_dracutmodules " == *\ $_mod\ * ]]; then | |
31f1c02d AW |
1365 | module_check $_mod 1; ret=$? |
1366 | else | |
1367 | module_check $_mod 0; ret=$? | |
1368 | fi | |
95d2dabc HH |
1369 | # explicit module, so also accept ret=255 |
1370 | [[ $ret = 0 || $ret = 255 ]] || return 1 | |
1371 | else | |
1372 | # module not in our list | |
1373 | if [[ $dracutmodules = all ]]; then | |
1374 | # check, if we can and should install this module | |
29b10e65 | 1375 | module_check $_mod || return 1 |
cc02093d | 1376 | else |
95d2dabc HH |
1377 | # skip this module |
1378 | return 1 | |
970e646b | 1379 | fi |
95d2dabc | 1380 | fi |
bb764545 | 1381 | |
29b10e65 | 1382 | for _moddep in $(module_depends $_mod); do |
95d2dabc | 1383 | # handle deps as if they were manually added |
b093aa2d | 1384 | [[ " $add_dracutmodules " == *\ $_moddep\ * ]] || \ |
29b10e65 | 1385 | add_dracutmodules+=" $_moddep " |
b093aa2d | 1386 | [[ " $force_add_dracutmodules " == *\ $_moddep\ * ]] || \ |
31f1c02d | 1387 | force_add_dracutmodules+=" $_moddep " |
95d2dabc | 1388 | # if a module we depend on fail, fail also |
0f283709 | 1389 | if ! check_module $_moddep; then |
600c8769 | 1390 | derror "dracut module '$_mod' depends on '$_moddep', which can't be installed" |
0f283709 HH |
1391 | return 1 |
1392 | fi | |
0c2e3d12 | 1393 | done |
70503db4 | 1394 | |
b093aa2d | 1395 | [[ " $mods_to_load " == *\ $_mod\ * ]] || \ |
29b10e65 | 1396 | mods_to_load+=" $_mod " |
95d2dabc HH |
1397 | |
1398 | return 0 | |
1399 | } | |
1400 | ||
7e2bca48 HH |
1401 | # for_each_module_dir <func> |
1402 | # execute "<func> <dracut module> 1" | |
1b7fd0fa | 1403 | for_each_module_dir() { |
29b10e65 HH |
1404 | local _modcheck |
1405 | local _mod | |
1406 | local _moddir | |
1b7fd0fa AW |
1407 | local _func |
1408 | _func=$1 | |
29b10e65 | 1409 | for _moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do |
00ed3ccf HH |
1410 | [[ -d $_moddir ]] || continue; |
1411 | [[ -e $_moddir/install || -e $_moddir/installkernel || \ | |
1412 | -e $_moddir/module-setup.sh ]] || continue | |
29b10e65 | 1413 | _mod=${_moddir##*/}; _mod=${_mod#[0-9][0-9]} |
1b7fd0fa | 1414 | $_func $_mod 1 |
70503db4 | 1415 | done |
724b87a6 HH |
1416 | |
1417 | # Report any missing dracut modules, the user has specified | |
31f1c02d | 1418 | _modcheck="$add_dracutmodules $force_add_dracutmodules" |
29b10e65 HH |
1419 | [[ $dracutmodules != all ]] && _modcheck="$m $dracutmodules" |
1420 | for _mod in $_modcheck; do | |
b093aa2d HH |
1421 | [[ " $mods_to_load " == *\ $_mod\ * ]] && continue |
1422 | [[ " $omit_dracutmodules " == *\ $_mod\ * ]] && continue | |
600c8769 | 1423 | derror "dracut module '$_mod' cannot be found or installed." |
724b87a6 | 1424 | done |
0c2e3d12 VL |
1425 | } |
1426 | ||
ddfd1d10 VL |
1427 | # Install a single kernel module along with any firmware it may require. |
1428 | # $1 = full path to kernel module to install | |
1429 | install_kmod_with_fw() { | |
0b440844 | 1430 | # no need to go further if the module is already installed |
379c34d2 | 1431 | |
0b706743 AŻ |
1432 | [[ -e "${initdir}/lib/modules/$kernel/${1##*/lib/modules/$kernel/}" ]] \ |
1433 | && return 0 | |
fcbcb252 | 1434 | |
f4031e8a HH |
1435 | if [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && [[ -e "$DRACUT_KERNEL_LAZY_HASHDIR/${1##*/}" ]]; then |
1436 | read ret < "$DRACUT_KERNEL_LAZY_HASHDIR/${1##*/}" | |
d8aeb3a7 HH |
1437 | return $ret |
1438 | fi | |
379c34d2 | 1439 | |
fcbcb252 HH |
1440 | if [[ $omit_drivers ]]; then |
1441 | local _kmod=${1##*/} | |
1442 | _kmod=${_kmod%.ko} | |
1443 | _kmod=${_kmod/-/_} | |
34248c92 HH |
1444 | if [[ "$_kmod" =~ $omit_drivers ]]; then |
1445 | dinfo "Omitting driver $_kmod" | |
7abd4264 | 1446 | return 0 |
34248c92 HH |
1447 | fi |
1448 | if [[ "${1##*/lib/modules/$kernel/}" =~ $omit_drivers ]]; then | |
fcbcb252 | 1449 | dinfo "Omitting driver $_kmod" |
7abd4264 | 1450 | return 0 |
fcbcb252 HH |
1451 | fi |
1452 | fi | |
1453 | ||
868f935e HH |
1454 | if [[ $silent_omit_drivers ]]; then |
1455 | local _kmod=${1##*/} | |
1456 | _kmod=${_kmod%.ko} | |
1457 | _kmod=${_kmod/-/_} | |
1458 | [[ "$_kmod" =~ $silent_omit_drivers ]] && return 0 | |
1459 | [[ "${1##*/lib/modules/$kernel/}" =~ $silent_omit_drivers ]] && return 0 | |
1460 | fi | |
1461 | ||
d8aeb3a7 HH |
1462 | inst_simple "$1" "/lib/modules/$kernel/${1##*/lib/modules/$kernel/}" |
1463 | ret=$? | |
f4031e8a HH |
1464 | [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && \ |
1465 | [[ -d "$DRACUT_KERNEL_LAZY_HASHDIR" ]] && \ | |
1466 | echo $ret > "$DRACUT_KERNEL_LAZY_HASHDIR/${1##*/}" | |
d8aeb3a7 | 1467 | (($ret != 0)) && return $ret |
e6024e00 JR |
1468 | |
1469 | local _modname=${1##*/} _fwdir _found _fw | |
1470 | _modname=${_modname%.ko*} | |
29b10e65 HH |
1471 | for _fw in $(modinfo -k $kernel -F firmware $1 2>/dev/null); do |
1472 | _found='' | |
1473 | for _fwdir in $fw_dir; do | |
1474 | if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then | |
1475 | inst_simple "$_fwdir/$_fw" "/lib/firmware/$_fw" | |
1476 | _found=yes | |
cc02093d HH |
1477 | fi |
1478 | done | |
29b10e65 | 1479 | if [[ $_found != yes ]]; then |
fe1484f3 | 1480 | if ! [[ -d $(echo /sys/module/${_modname//-/_}|{ read a b; echo $a; }) ]]; then |
29b10e65 HH |
1481 | dinfo "Possible missing firmware \"${_fw}\" for kernel module" \ |
1482 | "\"${_modname}.ko\"" | |
e2cdb570 | 1483 | else |
29b10e65 HH |
1484 | dwarn "Possible missing firmware \"${_fw}\" for kernel module" \ |
1485 | "\"${_modname}.ko\"" | |
e2cdb570 | 1486 | fi |
cc02093d | 1487 | fi |
ddfd1d10 | 1488 | done |
0b440844 | 1489 | return 0 |
ddfd1d10 VL |
1490 | } |
1491 | ||
1492 | # Do something with all the dependencies of a kernel module. | |
1493 | # Note that kernel modules depend on themselves using the technique we use | |
0b706743 AŻ |
1494 | # $1 = function to call for each dependency we find |
1495 | # It will be passed the full path to the found kernel module | |
ddfd1d10 VL |
1496 | # $2 = module to get dependencies for |
1497 | # rest of args = arguments to modprobe | |
c32bda6b | 1498 | # _fderr specifies FD passed from surrounding scope |
ddfd1d10 | 1499 | for_each_kmod_dep() { |
7abd4264 | 1500 | local _func=$1 _kmod=$2 _cmd _modpath _options |
ddfd1d10 | 1501 | shift 2 |
c32bda6b | 1502 | modprobe "$@" --ignore-install --show-depends $_kmod 2>&${_fderr} | ( |
29b10e65 HH |
1503 | while read _cmd _modpath _options; do |
1504 | [[ $_cmd = insmod ]] || continue | |
1505 | $_func ${_modpath} || exit $? | |
0b706743 | 1506 | done |
0b706743 | 1507 | ) |
ddfd1d10 VL |
1508 | } |
1509 | ||
70c6b773 | 1510 | dracut_kernel_post() { |
d8aeb3a7 | 1511 | local _moddirname=${srcmods%%/lib/modules/*} |
3c4bfd68 | 1512 | local _pid |
d8aeb3a7 | 1513 | |
f4031e8a | 1514 | if [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && [[ -f "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist" ]]; then |
ffc68f35 | 1515 | xargs -r modprobe -a ${_moddirname:+-d ${_moddirname}/} \ |
ec61f0a3 | 1516 | --ignore-install --show-depends --set-version $kernel \ |
f4031e8a | 1517 | < "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist" 2>/dev/null \ |
89d44e72 HH |
1518 | | sort -u \ |
1519 | | while read _cmd _modpath _options; do | |
1520 | [[ $_cmd = insmod ]] || continue | |
1521 | echo "$_modpath" | |
f4031e8a | 1522 | done > "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist.dep" |
d8aeb3a7 | 1523 | |
89d44e72 | 1524 | ( |
73575f11 | 1525 | if [[ $DRACUT_INSTALL ]] && [[ -z $_moddirname ]]; then |
ffc68f35 | 1526 | xargs -r $DRACUT_INSTALL ${initdir:+-D "$initdir"} -a < "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist.dep" |
89d44e72 HH |
1527 | else |
1528 | while read _modpath; do | |
1529 | local _destpath=$_modpath | |
1530 | [[ $_moddirname ]] && _destpath=${_destpath##$_moddirname/} | |
1531 | _destpath=${_destpath##*/lib/modules/$kernel/} | |
1532 | inst_simple "$_modpath" "/lib/modules/$kernel/${_destpath}" || exit $? | |
f4031e8a | 1533 | done < "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist.dep" |
89d44e72 HH |
1534 | fi |
1535 | ) & | |
dba20559 HH |
1536 | _pid=$(jobs -p | while read a ; do printf ":$a";done) |
1537 | _pid=${_pid##*:} | |
d8aeb3a7 | 1538 | |
73575f11 HH |
1539 | if [[ $DRACUT_INSTALL ]]; then |
1540 | xargs -r modinfo -k $kernel -F firmware < "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist.dep" \ | |
89d44e72 HH |
1541 | | while read line; do |
1542 | for _fwdir in $fw_dir; do | |
1543 | echo $_fwdir/$line; | |
1544 | done; | |
ffc68f35 | 1545 | done | xargs -r $DRACUT_INSTALL ${initdir:+-D "$initdir"} -a -o |
89d44e72 | 1546 | else |
73575f11 | 1547 | for _fw in $(xargs -r modinfo -k $kernel -F firmware < "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist.dep"); do |
89d44e72 HH |
1548 | for _fwdir in $fw_dir; do |
1549 | if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then | |
1550 | inst_simple "$_fwdir/$_fw" "/lib/firmware/$_fw" | |
1551 | break | |
1552 | fi | |
1553 | done | |
1554 | done | |
1555 | fi | |
d8aeb3a7 | 1556 | |
3c4bfd68 | 1557 | wait $_pid |
89d44e72 | 1558 | fi |
70c6b773 | 1559 | |
70c6b773 HH |
1560 | for _f in modules.builtin.bin modules.builtin modules.order; do |
1561 | [[ $srcmods/$_f ]] && inst_simple "$srcmods/$_f" "/lib/modules/$kernel/$_f" | |
1562 | done | |
1563 | ||
1564 | # generate module dependencies for the initrd | |
1565 | if [[ -d $initdir/lib/modules/$kernel ]] && \ | |
1566 | ! depmod -a -b "$initdir" $kernel; then | |
1567 | dfatal "\"depmod -a $kernel\" failed." | |
1568 | exit 1 | |
1569 | fi | |
1570 | ||
32bd2fbb | 1571 | [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && rm -fr -- "$DRACUT_KERNEL_LAZY_HASHDIR" |
d8aeb3a7 | 1572 | } |
fe1484f3 | 1573 | |
3c4315fa HH |
1574 | [[ "$kernel_current" ]] || export kernel_current=$(uname -r) |
1575 | ||
dba20559 | 1576 | module_is_host_only() { |
080d1b71 | 1577 | local _mod=$1 |
4d7c18c7 | 1578 | local _modenc a i _k _s _v _aliases |
080d1b71 HH |
1579 | _mod=${_mod##*/} |
1580 | _mod=${_mod%.ko} | |
3c4315fa | 1581 | _modenc=${_mod//-/_} |
080d1b71 | 1582 | |
b093aa2d | 1583 | [[ " $add_drivers " == *\ ${_mod}\ * ]] && return 0 |
080d1b71 HH |
1584 | |
1585 | # check if module is loaded | |
3c4315fa HH |
1586 | [[ ${host_modules["$_modenc"]} ]] && return 0 |
1587 | ||
1588 | [[ "$kernel_current" ]] || export kernel_current=$(uname -r) | |
1589 | ||
1590 | if [[ "$kernel_current" != "$kernel" ]]; then | |
1591 | # check if module is loadable on the current kernel | |
1592 | # this covers the case, where a new module is introduced | |
1593 | # or a module was renamed | |
1594 | # or a module changed from builtin to a module | |
4d7c18c7 | 1595 | |
3c4315fa HH |
1596 | if [[ -d /lib/modules/$kernel_current ]]; then |
1597 | # if the modinfo can be parsed, but the module | |
1598 | # is not loaded, then we can safely return 1 | |
1599 | modinfo -F filename "$_mod" &>/dev/null && return 1 | |
1600 | fi | |
080d1b71 | 1601 | |
4d7c18c7 HH |
1602 | _aliases=$(modinfo -k $kernel -F alias $_mod 2>/dev/null) |
1603 | ||
1604 | # if the module has no aliases, install it | |
1605 | [[ $_aliases ]] || return 0 | |
1606 | ||
1607 | # finally check all modalias | |
1608 | for a in $_aliases; do | |
3c4315fa HH |
1609 | for i in "${!host_modalias[@]}"; do |
1610 | [[ $i == $a ]] && return 0 | |
1611 | done | |
1612 | done | |
4d7c18c7 | 1613 | |
3c4315fa | 1614 | fi |
080d1b71 HH |
1615 | |
1616 | return 1 | |
b093aa2d | 1617 | } |
080d1b71 | 1618 | |
b093aa2d | 1619 | find_kernel_modules_by_path () { |
74405477 | 1620 | local _OLDIFS |
5db6ca5a | 1621 | |
b093aa2d | 1622 | [[ -f "$srcmods/modules.dep" ]] || return 0 |
5db6ca5a HH |
1623 | |
1624 | _OLDIFS=$IFS | |
1625 | IFS=: | |
1626 | while read a rest; do | |
e8a7c9bc | 1627 | [[ $a = */$1/* ]] || [[ $a = updates/* ]] || continue |
b093aa2d HH |
1628 | printf "%s\n" "$srcmods/$a" |
1629 | done < "$srcmods/modules.dep" | |
5db6ca5a | 1630 | IFS=$_OLDIFS |
74405477 | 1631 | return 0 |
b093aa2d | 1632 | } |
4073c815 | 1633 | |
881eda69 JR |
1634 | find_kernel_modules () { |
1635 | find_kernel_modules_by_path drivers | |
1636 | } | |
1637 | ||
338b43cd HH |
1638 | # instmods [-c [-s]] <kernel module> [<kernel module> ... ] |
1639 | # instmods [-c [-s]] <kernel subsystem> | |
ddfd1d10 | 1640 | # install kernel modules along with all their dependencies. |
7e2bca48 | 1641 | # <kernel subsystem> can be e.g. "=block" or "=drivers/usb/storage" |
6fa0c3d6 | 1642 | instmods() { |
0c1a8ebc | 1643 | [[ $no_kernel = yes ]] && return |
c32bda6b MS |
1644 | # called [sub]functions inherit _fderr |
1645 | local _fderr=9 | |
a6d3be9d | 1646 | local _check=no |
338b43cd | 1647 | local _silent=no |
a6d3be9d AW |
1648 | if [[ $1 = '-c' ]]; then |
1649 | _check=yes | |
1650 | shift | |
1651 | fi | |
881eda69 | 1652 | |
338b43cd HH |
1653 | if [[ $1 = '-s' ]]; then |
1654 | _silent=yes | |
1655 | shift | |
1656 | fi | |
1657 | ||
881eda69 | 1658 | function inst1mod() { |
a6d3be9d | 1659 | local _ret=0 _mod="$1" |
29b10e65 | 1660 | case $_mod in |
0b706743 | 1661 | =*) |
d8aeb3a7 HH |
1662 | ( [[ "$_mpargs" ]] && echo $_mpargs |
1663 | find_kernel_modules_by_path "${_mod#=}" ) \ | |
1664 | | instmods | |
1665 | ((_ret+=$?)) | |
cc02093d | 1666 | ;; |
0024702f | 1667 | --*) _mpargs+=" $_mod" ;; |
34248c92 | 1668 | *) |
379c34d2 | 1669 | _mod=${_mod##*/} |
6568d86a | 1670 | # if we are already installed, skip this module and go on |
cc02093d | 1671 | # to the next one. |
f4031e8a HH |
1672 | if [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && \ |
1673 | [[ -f "$DRACUT_KERNEL_LAZY_HASHDIR/${_mod%.ko}.ko" ]]; then | |
1674 | read _ret <"$DRACUT_KERNEL_LAZY_HASHDIR/${_mod%.ko}.ko" | |
d8aeb3a7 HH |
1675 | return $_ret |
1676 | fi | |
881eda69 | 1677 | |
beb26a08 DY |
1678 | _mod=${_mod/-/_} |
1679 | if [[ $omit_drivers ]] && [[ "$_mod" =~ $omit_drivers ]]; then | |
34248c92 | 1680 | dinfo "Omitting driver ${_mod##$srcmods}" |
7abd4264 | 1681 | return 0 |
34248c92 | 1682 | fi |
080d1b71 | 1683 | |
cc02093d HH |
1684 | # If we are building a host-specific initramfs and this |
1685 | # module is not already loaded, move on to the next one. | |
fe1484f3 | 1686 | [[ $hostonly ]] \ |
080d1b71 | 1687 | && ! module_is_host_only "$_mod" \ |
7abd4264 | 1688 | && return 0 |
04b56f3a | 1689 | |
f4031e8a | 1690 | if [[ "$_check" = "yes" ]] || ! [[ $DRACUT_KERNEL_LAZY_HASHDIR ]]; then |
d8aeb3a7 | 1691 | # We use '-d' option in modprobe only if modules prefix path |
600c8769 | 1692 | # differs from default '/'. This allows us to use dracut with |
d8aeb3a7 HH |
1693 | # old version of modprobe which doesn't have '-d' option. |
1694 | local _moddirname=${srcmods%%/lib/modules/*} | |
1695 | [[ -n ${_moddirname} ]] && _moddirname="-d ${_moddirname}/" | |
1696 | ||
1697 | # ok, load the module, all its dependencies, and any firmware | |
1698 | # it may require | |
1699 | for_each_kmod_dep install_kmod_with_fw $_mod \ | |
1700 | --set-version $kernel ${_moddirname} $_mpargs | |
1701 | ((_ret+=$?)) | |
1702 | else | |
f4031e8a HH |
1703 | [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && \ |
1704 | echo $_mod >> "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist" | |
d8aeb3a7 | 1705 | fi |
cc02093d | 1706 | ;; |
0b706743 | 1707 | esac |
a6d3be9d | 1708 | return $_ret |
881eda69 JR |
1709 | } |
1710 | ||
f9708da2 | 1711 | function instmods_1() { |
a6d3be9d | 1712 | local _mod _mpargs |
f9708da2 JR |
1713 | if (($# == 0)); then # filenames from stdin |
1714 | while read _mod; do | |
a6d3be9d | 1715 | inst1mod "${_mod%.ko*}" || { |
338b43cd | 1716 | if [[ "$_check" == "yes" ]]; then |
19b5c109 | 1717 | [[ "$_silent" == "no" ]] && dfatal "Failed to install module $_mod" |
a6d3be9d AW |
1718 | return 1 |
1719 | fi | |
1720 | } | |
f9708da2 JR |
1721 | done |
1722 | fi | |
1723 | while (($# > 0)); do # filenames as arguments | |
a6d3be9d | 1724 | inst1mod ${1%.ko*} || { |
338b43cd | 1725 | if [[ "$_check" == "yes" ]]; then |
19b5c109 | 1726 | [[ "$_silent" == "no" ]] && dfatal "Failed to install module $1" |
a6d3be9d AW |
1727 | return 1 |
1728 | fi | |
1729 | } | |
f9708da2 | 1730 | shift |
881eda69 | 1731 | done |
a6d3be9d | 1732 | return 0 |
f9708da2 JR |
1733 | } |
1734 | ||
a6d3be9d | 1735 | local _ret _filter_not_found='FATAL: Module .* not found.' |
c32bda6b MS |
1736 | # Capture all stderr from modprobe to _fderr. We could use {var}>... |
1737 | # redirections, but that would make dracut require bash4 at least. | |
1738 | eval "( instmods_1 \"\$@\" ) ${_fderr}>&1" \ | |
dba20559 | 1739 | | while read line; do [[ "$line" =~ $_filter_not_found ]] || echo $line;done | derror |
a6d3be9d | 1740 | _ret=$? |
a6d3be9d | 1741 | return $_ret |
0b706743 | 1742 | } |
5f2c30d9 KRW |
1743 | # get_cpu_vendor |
1744 | # Only two values are returned: AMD or Intel | |
1745 | get_cpu_vendor () | |
1746 | { | |
1747 | if grep -qE AMD /proc/cpuinfo; then | |
1748 | printf "AMD" | |
1749 | fi | |
1750 | if grep -qE Intel /proc/cpuinfo; then | |
1751 | printf "Intel" | |
1752 | fi | |
1753 | } | |
1754 | ||
1755 | # get_host_ucode | |
1756 | # Get the hosts' ucode file based on the /proc/cpuinfo | |
1757 | get_ucode_file () | |
1758 | { | |
1759 | local family=`grep -E "cpu family" /proc/cpuinfo | head -1 | sed s/.*:\ //` | |
1760 | local model=`grep -E "model" /proc/cpuinfo |grep -v name | head -1 | sed s/.*:\ //` | |
1761 | local stepping=`grep -E "stepping" /proc/cpuinfo | head -1 | sed s/.*:\ //` | |
1762 | ||
1763 | if [[ "$(get_cpu_vendor)" == "AMD" ]]; then | |
1764 | # If family greater or equal than 0x15 | |
1765 | if [[ $family -ge 21 ]]; then | |
1766 | printf "microcode_amd_fam15h.bin" | |
1767 | else | |
1768 | printf "microcode_amd.bin" | |
1769 | fi | |
1770 | fi | |
1771 | if [[ "$(get_cpu_vendor)" == "Intel" ]]; then | |
1772 | # The /proc/cpuinfo are in decimal. | |
1773 | printf "%02x-%02x-%02x" ${family} ${model} ${stepping} | |
1774 | fi | |
1775 | } | |
96c6f6f3 MC |
1776 | |
1777 | # Not every device in /dev/mapper should be examined. | |
1778 | # If it is an LVM device, touch only devices which have /dev/VG/LV symlink. | |
1779 | lvm_internal_dev() { | |
1780 | local dev_dm_dir=/sys/dev/block/$1/dm | |
1781 | [[ ! -f $dev_dm_dir/uuid || $(<$dev_dm_dir/uuid) != LVM-* ]] && return 1 # Not an LVM device | |
1782 | local DM_VG_NAME DM_LV_NAME DM_LV_LAYER | |
1783 | eval $(dmsetup splitname --nameprefixes --noheadings --rows "$(<$dev_dm_dir/name)" 2>/dev/null) | |
1784 | [[ ${DM_VG_NAME} ]] && [[ ${DM_LV_NAME} ]] || return 0 # Better skip this! | |
1785 | [[ ${DM_LV_LAYER} ]] || [[ ! -L /dev/${DM_VG_NAME}/${DM_LV_NAME} ]] | |
1786 | } | |
1787 |