3 # functions used by dracut and other tools.
5 # Copyright 2005-2009 Red Hat, Inc. All rights reserved.
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 # Check whether $1 is a function.
25 [[ "$(type -t "$1")" == "function" ]]
28 # Generic substring function. If $2 is in $1, return 0.
29 strstr
() { [[ $1 == *"$2"* ]]; }
30 # Generic glob matching function. If glob pattern $2 matches anywhere in $1, OK
31 strglobin
() { [[ $1 == *$2* ]]; }
32 # Generic glob matching function. If glob pattern $2 matches all of $1, OK
33 # shellcheck disable=SC2053
34 strglob
() { [[ $1 == $2 ]]; }
35 # returns OK if $1 contains literal string $2 at the beginning, and isn't empty
36 str_starts
() { [ "${1#"$2"*}" != "$1" ]; }
37 # returns OK if $1 contains literal string $2 at the end, and isn't empty
38 str_ends
() { [ "${1%*"$2"}" != "$1" ]; }
40 # find a binary. If we were not passed the full path directly,
41 # search in the usual places to find the binary.
47 [[ -z ${1##/*} ]] || _delim
="/"
49 if [[ $1 == *.so
* ]]; then
50 # shellcheck disable=SC2154
52 _path
="${l}${_delim}${1}"
53 if { $DRACUT_LDD "${dracutsysrootdir}${_path}" &> /dev/null; }; then
54 printf "%s
\n" "${_path}"
59 if { $DRACUT_LDD "${dracutsysrootdir}${_path}" &> /dev/null; }; then
60 printf "%s\n" "${_path}"
64 if [[ $1 == */* ]]; then
66 if [[ -L ${dracutsysrootdir}${_path} ]] || [[ -x ${dracutsysrootdir}${_path} ]]; then
67 printf "%s\n" "${_path}"
71 for p
in $DRACUT_PATH; do
72 _path
="${p}${_delim}${1}"
73 if [[ -L ${dracutsysrootdir}${_path} ]] || [[ -x ${dracutsysrootdir}${_path} ]]; then
74 printf "%s\n" "${_path}"
79 [[ -n $dracutsysrootdir ]] && return 1
84 $DRACUT_LDCONFIG ${dracutsysrootdir:+-r ${dracutsysrootdir} -f /etc/ld.so.conf} -pN 2> /dev
/null |
grep -E -v '/(lib|lib64|usr/lib|usr/lib64)/[^/]*$' |
sed -n 's,.* => \(.*\)/.*,\1,p' |
sort |
uniq
87 # Version comparision function. Assumes Linux style version scheme.
89 # $2 = comparision op (gt, ge, eq, le, lt, ne)
93 read -r -a _n1
<<< "${1//./ }"
96 read -r -a _n2
<<< "${3//./ }"
99 for ((_i
= 0; ; _i
++)); do
100 if [[ ! ${_n1[_i]}${_n2[_i]} ]]; then
102 elif ((${_n1[_i]:-0} > ${_n2[_i]:-0})); then
104 elif ((${_n1[_i]:-0} < ${_n2[_i]:-0})); then
122 # Create all subdirectories for given path without creating the last element.
125 # shellcheck disable=SC2174
126 [[ -e ${1%/*} ]] || mkdir
-m 0755 -p -- "${1%/*}"
129 # Function prints global variables in format name=value line by line.
130 # $@ = list of global variables' name
135 eval printf -v _value
"%s" \""\$$_var"\"
136 [[ ${_value} ]] && printf '%s="%s"\n' "$_var" "$_value"
140 # normalize_path <path>
141 # Prints the normalized path, where it removes any duplicated
142 # and trailing slashes.
144 # $ normalize_path ///test/test//
147 # shellcheck disable=SC2064
148 trap "$(shopt -p extglob)" RETURN
150 local p
=${1//+(\/)//}
151 printf "%s\n" "${p%/}"
154 # convert_abs_rel <from> <to>
155 # Prints the relative path, when creating a symlink to <to> from <from>.
157 # $ convert_abs_rel /usr/bin/test /bin/test-2
159 # $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
161 local __current __absolute __abssize __cursize __newpath
164 set -- "$(normalize_path "$1")" "$(normalize_path "$2")"
166 # corner case #1 - self looping link
167 [[ $1 == "$2" ]] && {
168 printf "%s\n" "${1##*/}"
172 # corner case #2 - own dir link
173 [[ ${1%/*} == "$2" ]] && {
178 IFS
=/ read -r -a __current
<<< "$1"
179 IFS
=/ read -r -a __absolute
<<< "$2"
181 __abssize
=${#__absolute[@]}
182 __cursize
=${#__current[@]}
184 while [[ ${__absolute[__level]} == "${__current[__level]}" ]]; do
186 if ((__level
> __abssize || __level
> __cursize
)); then
191 for ((__i
= __level
; __i
< __cursize
- 1; __i
++)); do
192 if ((__i
> __level
)); then
193 __newpath
=$__newpath"/"
195 __newpath
=$__newpath".."
198 for ((__i
= __level
; __i
< __abssize
; __i
++)); do
199 if [[ -n $__newpath ]]; then
200 __newpath
=$__newpath"/"
202 __newpath
=$__newpath${__absolute[__i]}
205 printf -- "%s\n" "$__newpath"
208 # get_fs_env <device>
209 # Get and the ID_FS_TYPE variable from udev for a device.
211 # $ get_fs_env /dev/sda2
216 ID_FS_TYPE
=$
(blkid
-u filesystem
-o export -- "$1" \
217 |
while read -r line ||
[ -n "$line" ]; do
218 if [[ $line == "TYPE="* ]]; then
219 printf "%s" "${line#TYPE=}"
223 if [[ $ID_FS_TYPE ]]; then
224 printf "%s" "$ID_FS_TYPE"
230 # get_maj_min <device>
231 # Prints the major and minor of a device node.
233 # $ get_maj_min /dev/sda2
239 if [[ $get_maj_min_cache_file ]]; then
240 _out
="$(grep -m1 -oP "^
$1 \K\S
+$
" "$get_maj_min_cache_file")"
243 if ! [[ "$_out" ]]; then
244 _majmin
="$(stat -L -c '%t:%T' "$1" 2> /dev/null)"
245 _out
="$(printf "%s
" "$
((0x
${_majmin%:*})):$
((0x
${_majmin#*:}))")"
246 if [[ $get_maj_min_cache_file ]]; then
247 echo "$1 $_out" >> "$get_maj_min_cache_file"
253 # get_devpath_block <device>
254 # get the DEVPATH in /sys of a block device
255 get_devpath_block
() {
257 _majmin
=$
(get_maj_min
"$1")
259 for _i
in /sys
/block
/*/dev
/sys
/block
/*/*/dev
; do
260 [[ -e $_i ]] ||
continue
261 if [[ $_majmin == "$(< "$_i")" ]]; then
262 printf "%s" "${_i%/dev}"
269 # get a persistent path from a device
270 get_persistent_dev
() {
271 local i _tmp _dev _pol
273 _dev
=$
(get_maj_min
"$1")
274 [ -z "$_dev" ] && return
276 if [[ -n $persistent_policy ]]; then
277 _pol
="/dev/disk/${persistent_policy}/*"
285 /dev
/disk
/by-uuid
/* \
286 /dev
/disk
/by-label
/* \
287 /dev
/disk
/by-partuuid
/* \
288 /dev
/disk
/by-partlabel
/* \
290 /dev
/disk
/by-path
/*; do
291 [[ -e $i ]] ||
continue
292 [[ $i == /dev
/mapper
/control
]] && continue
293 [[ $i == /dev
/mapper
/mpath
* ]] && continue
294 _tmp
=$
(get_maj_min
"$i")
295 if [ "$_tmp" = "$_dev" ]; then
303 expand_persistent_dev
() {
308 _dev
="/dev/disk/by-label/${_dev#LABEL=}"
313 _dev
="/dev/disk/by-uuid/${_dev}"
316 _dev
="${_dev#PARTUUID=}"
318 _dev
="/dev/disk/by-partuuid/${_dev}"
321 _dev
="/dev/disk/by-partlabel/${_dev#PARTLABEL=}"
327 shorten_persistent_dev
() {
331 printf "%s" "UUID=${_dev##*/}"
333 /dev
/disk
/by-label
/*)
334 printf "%s" "LABEL=${_dev##*/}"
336 /dev
/disk
/by-partuuid
/*)
337 printf "%s" "PARTUUID=${_dev##*/}"
339 /dev
/disk
/by-partlabel
/*)
340 printf "%s" "PARTLABEL=${_dev##*/}"
348 # find_block_device <mountpoint>
349 # Prints the major and minor number of the block device
350 # for a given mountpoint.
351 # Unless $use_fstab is set to "yes" the functions
352 # uses /proc/self/mountinfo as the primary source of the
353 # information and only falls back to /etc/fstab, if the mountpoint
354 # is not found there.
356 # $ find_block_device /usr
358 find_block_device
() {
359 local _dev _majmin _find_mpt
362 if [[ $use_fstab != yes ]]; then
363 [[ -d $_find_mpt/.
]]
364 findmnt
-e -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" |
{
365 while read -r _majmin _dev ||
[ -n "$_dev" ]; do
366 if [[ -b $_dev ]]; then
367 if ! [[ $_majmin ]] ||
[[ $_majmin == 0:* ]]; then
368 _majmin
=$
(get_maj_min
"$_dev")
370 if [[ $_majmin ]]; then
371 printf "%s\n" "$_majmin"
373 printf "%s\n" "$_dev"
377 if [[ $_dev == *:* ]]; then
378 printf "%s\n" "$_dev"
385 # fall back to /etc/fstab
387 findmnt
-e --fstab -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" |
{
388 while read -r _majmin _dev ||
[ -n "$_dev" ]; do
389 if ! [[ $_dev ]]; then
393 if [[ -b $_dev ]]; then
394 [[ $_majmin ]] || _majmin
=$
(get_maj_min
"$_dev")
395 if [[ $_majmin ]]; then
396 printf "%s\n" "$_majmin"
398 printf "%s\n" "$_dev"
402 if [[ $_dev == *:* ]]; then
403 printf "%s\n" "$_dev"
413 # find_mp_fstype <mountpoint>
414 # Echo the filesystem type for a given mountpoint.
415 # /proc/self/mountinfo is taken as the primary source of information
416 # and /etc/fstab is used as a fallback.
417 # No newline is appended!
419 # $ find_mp_fstype /;echo
424 if [[ $use_fstab != yes ]]; then
425 findmnt
-e -v -n -o 'FSTYPE' --target "$1" |
{
426 while read -r _fs ||
[ -n "$_fs" ]; do
427 [[ $_fs ]] ||
continue
428 [[ $_fs == "autofs" ]] && continue
436 findmnt
--fstab -e -v -n -o 'FSTYPE' --target "$1" |
{
437 while read -r _fs ||
[ -n "$_fs" ]; do
438 [[ $_fs ]] ||
continue
439 [[ $_fs == "autofs" ]] && continue
449 # find_dev_fstype <device>
450 # Echo the filesystem type for a given device.
451 # /proc/self/mountinfo is taken as the primary source of information
452 # and /etc/fstab is used as a fallback.
453 # No newline is appended!
455 # $ find_dev_fstype /dev/sda2;echo
460 if ! [[ $_find_dev == /dev
* ]]; then
461 [[ -b "/dev/block/$_find_dev" ]] && _find_dev
="/dev/block/$_find_dev"
464 if [[ $use_fstab != yes ]]; then
465 findmnt
-e -v -n -o 'FSTYPE' --source "$_find_dev" |
{
466 while read -r _fs ||
[ -n "$_fs" ]; do
467 [[ $_fs ]] ||
continue
468 [[ $_fs == "autofs" ]] && continue
476 findmnt
--fstab -e -v -n -o 'FSTYPE' --source "$_find_dev" |
{
477 while read -r _fs ||
[ -n "$_fs" ]; do
478 [[ $_fs ]] ||
continue
479 [[ $_fs == "autofs" ]] && continue
489 # find_mp_fsopts <mountpoint>
490 # Echo the filesystem options for a given mountpoint.
491 # /proc/self/mountinfo is taken as the primary source of information
492 # and /etc/fstab is used as a fallback.
493 # No newline is appended!
495 # $ find_mp_fsopts /;echo
496 # rw,relatime,discard,data=ordered
498 if [[ $use_fstab != yes ]]; then
499 findmnt
-e -v -n -o 'OPTIONS' --target "$1" 2> /dev
/null
&& return 0
502 findmnt
--fstab -e -v -n -o 'OPTIONS' --target "$1"
505 # find_dev_fsopts <device>
506 # Echo the filesystem options for a given device.
507 # /proc/self/mountinfo is taken as the primary source of information
508 # and /etc/fstab is used as a fallback.
509 # if `use_fstab == yes`, then only `/etc/fstab` is used.
512 # $ find_dev_fsopts /dev/sda2
513 # rw,relatime,discard,data=ordered
517 if ! [[ $_find_dev == /dev
* ]]; then
518 [[ -b "/dev/block/$_find_dev" ]] && _find_dev
="/dev/block/$_find_dev"
521 if [[ $use_fstab != yes ]]; then
522 findmnt
-e -v -n -o 'OPTIONS' --source "$_find_dev" 2> /dev
/null
&& return 0
525 findmnt
--fstab -e -v -n -o 'OPTIONS' --source "$_find_dev"
528 # finds the major:minor of the block device backing the root filesystem.
529 find_root_block_device
() { find_block_device
/; }
531 # for_each_host_dev_fs <func>
532 # Execute "<func> <dev> <filesystem>" for every "<dev> <fs>" pair found
533 # in ${host_fs_types[@]}
534 for_each_host_dev_fs
() {
539 [[ "${#host_fs_types[@]}" ]] ||
return 2
541 for _dev
in "${!host_fs_types[@]}"; do
542 $_func "$_dev" "${host_fs_types[$_dev]}" && _ret
=0
548 printf "%s\n" "${host_fs_types[@]}"
551 # Walk all the slave relationships for a given block device.
552 # Stop when our helper function returns success
553 # $1 = function to call on every found block device
554 # $2 = block device in major:minor format
555 check_block_and_slaves
() {
557 [[ -b /dev
/block
/$2 ]] ||
return 1 # Not a block device? So sorry.
558 if ! lvm_internal_dev
"$2"; then "$1" "$2" && return; fi
559 check_vol_slaves
"$@" && return 0
560 if [[ -f /sys
/dev
/block
/$2/..
/dev
]] && [[ /sys
/dev
/block
/$2/..
/subsystem
-ef /sys
/class
/block
]]; then
561 check_block_and_slaves
"$1" "$(< "/sys
/dev
/block
/$2/..
/dev
")" && return 0
563 for _x
in /sys
/dev
/block
/"$2"/slaves
/*; do
564 [[ -f $_x/dev
]] ||
continue
565 [[ $_x/subsystem
-ef /sys
/class
/block
]] ||
continue
566 check_block_and_slaves
"$1" "$(< "$_x/dev
")" && return 0
571 check_block_and_slaves_all
() {
573 [[ -b /dev
/block
/$2 ]] ||
return 1 # Not a block device? So sorry.
574 if ! lvm_internal_dev
"$2" && "$1" "$2"; then
577 check_vol_slaves_all
"$@" && return 0
578 if [[ -f /sys
/dev
/block
/$2/..
/dev
]] && [[ /sys
/dev
/block
/$2/..
/subsystem
-ef /sys
/class
/block
]]; then
579 check_block_and_slaves_all
"$1" "$(< "/sys
/dev
/block
/$2/..
/dev
")" && _ret
=0
581 for _x
in /sys
/dev
/block
/"$2"/slaves
/*; do
582 [[ -f $_x/dev
]] ||
continue
583 [[ $_x/subsystem
-ef /sys
/class
/block
]] ||
continue
584 check_block_and_slaves_all
"$1" "$(< "$_x/dev
")" && _ret
=0
588 # for_each_host_dev_and_slaves <func>
589 # Execute "<func> <dev>" for every "<dev>" found
590 # in ${host_devs[@]} and their slaves
591 for_each_host_dev_and_slaves_all
() {
596 [[ "${host_devs[*]}" ]] ||
return 2
598 for _dev
in "${host_devs[@]}"; do
599 [[ -b $_dev ]] ||
continue
600 if check_block_and_slaves_all
"$_func" "$(get_maj_min "$_dev")"; then
607 for_each_host_dev_and_slaves
() {
611 [[ "${host_devs[*]}" ]] ||
return 2
613 for _dev
in "${host_devs[@]}"; do
614 [[ -b $_dev ]] ||
continue
615 check_block_and_slaves
"$_func" "$(get_maj_min "$_dev")" && return 0
620 # /sys/dev/block/major:minor is symbol link to real hardware device
621 # go downstream $(realpath /sys/dev/block/major:minor) to detect driver
622 get_blockdev_drv_through_sys
() {
626 _path
=$
(realpath
"$1")
628 if [[ -L "$_path"/driver
/module
]]; then
629 _mod
=$
(realpath
"$_path"/driver
/module
)
630 _mod
=$
(basename "$_mod")
631 _block_mods
="$_block_mods $_mod"
633 _path
=$
(dirname "$_path")
634 if [[ $_path == '/sys/devices' ]] ||
[[ $_path == '/' ]]; then
641 # ugly workaround for the lvm design
642 # There is no volume group device,
643 # so, there are no slave devices for volume groups.
644 # Logical volumes only have the slave devices they really live on,
645 # but you cannot create the logical volume without the volume group.
646 # And the volume group might be bigger than the devices the LV needs.
648 local _vg _pv _dm _majmin
650 _dm
=/sys
/dev
/block
/$_majmin/dm
651 [[ -f $_dm/uuid
&& $
(< "$_dm"/uuid
) =~ LVM-
* ]] ||
return 1
652 _vg
=$
(dmsetup splitname
--noheadings -o vg_name
"$(< "$_dm/name
")")
654 _vg
="${_vg//[[:space:]]/}"
656 for _pv
in $
(lvm vgs
--noheadings -o pv_name
"$_vg" 2> /dev
/null
); do
657 check_block_and_slaves
"$1" "$(get_maj_min "$_pv")" && return 0
663 check_vol_slaves_all
() {
664 local _vg _pv _majmin
666 _dm
="/sys/dev/block/$_majmin/dm"
667 [[ -f $_dm/uuid
&& $
(< "$_dm"/uuid
) =~ LVM-
* ]] ||
return 1
668 _vg
=$
(dmsetup splitname
--noheadings -o vg_name
"$(< "$_dm/name
")")
670 _vg
="${_vg//[[:space:]]/}"
672 # when filter/global_filter is set, lvm may be failed
673 if ! lvm lvs
--noheadings -o vg_name
"$_vg" 2> /dev
/null
1> /dev
/null
; then
677 for _pv
in $
(lvm vgs
--noheadings -o pv_name
"$_vg" 2> /dev
/null
); do
678 check_block_and_slaves_all
"$1" "$(get_maj_min "$_pv")"
685 # fs_get_option <filesystem options> <search for option>
686 # search for a specific option in a bunch of filesystem options
687 # and return the value
693 # shellcheck disable=SC2086
696 while [ $# -gt 0 ]; do
699 echo "${1#${_option}=}"
707 check_kernel_config
() {
708 local _config_opt
="$1"
710 [[ -f $dracutsysrootdir/boot
/config-
$kernel ]] \
711 && _config_file
="/boot/config-$kernel"
712 [[ -f $dracutsysrootdir/lib
/modules
/$kernel/config
]] \
713 && _config_file
="/lib/modules/$kernel/config"
715 # no kernel config file, so return true
716 [[ $_config_file ]] ||
return 0
718 grep -q -F "${_config_opt}=" "$dracutsysrootdir$_config_file" && return 0
722 # 0 if the kernel module is either built-in or available
723 # 1 if the kernel module is not enabled
724 check_kernel_module
() {
725 modprobe
-S "$kernel" --dry-run "$1" &> /dev
/null ||
return 1
729 # Only two values are returned: AMD or Intel
731 if grep -qE AMD
/proc
/cpuinfo
; then
734 if grep -qE Intel
/proc
/cpuinfo
; then
740 # Get the hosts' ucode file based on the /proc/cpuinfo
745 family
=$
(grep -E "cpu family" /proc
/cpuinfo |
head -1 |
sed "s/.*:\ //")
746 model
=$
(grep -E "model" /proc
/cpuinfo |
grep -v name |
head -1 |
sed "s/.*:\ //")
747 stepping
=$
(grep -E "stepping" /proc
/cpuinfo |
head -1 |
sed "s/.*:\ //")
749 if [[ "$(get_cpu_vendor)" == "AMD" ]]; then
750 if [[ $family -ge 21 ]]; then
751 printf "microcode_amd_fam%xh.bin" "$family"
753 printf "microcode_amd.bin"
756 if [[ "$(get_cpu_vendor)" == "Intel" ]]; then
757 # The /proc/cpuinfo are in decimal.
758 printf "%02x-%02x-%02x" "${family}" "${model}" "${stepping}"
762 # Not every device in /dev/mapper should be examined.
763 # If it is an LVM device, touch only devices which have /dev/VG/LV symlink.
765 local dev_dm_dir
=/sys
/dev
/block
/$1/dm
766 [[ ! -f $dev_dm_dir/uuid || $
(< "$dev_dm_dir"/uuid
) != LVM-
* ]] && return 1 # Not an LVM device
767 local DM_VG_NAME DM_LV_NAME DM_LV_LAYER
768 eval "$(dmsetup splitname --nameprefixes --noheadings --rows "$
(< "$dev_dm_dir"/name
)" 2> /dev/null)"
769 [[ ${DM_VG_NAME} ]] && [[ ${DM_LV_NAME} ]] ||
return 0 # Better skip this!
770 [[ ${DM_LV_LAYER} ]] || [[ ! -L /dev/${DM_VG_NAME}/${DM_LV_NAME} ]]
775 btrfs device usage
"$_mp" \
776 |
while read -r _dev _
; do
777 str_starts
"$_dev" "/" ||
continue
779 printf -- "%s\n" "$_dev"
785 zpool list
-H -v -P "${_mp%%/*}" |
awk -F$
'\t' '$2 ~ /^\// {print $2}' \
786 |
while read -r _dev
; do
791 iface_for_remote_addr
() {
792 # shellcheck disable=SC2046
793 set -- $
(ip
-o route get to
"$1")
794 while [ $# -gt 0 ]; do
805 local_addr_for_remote_addr
() {
806 # shellcheck disable=SC2046
807 set -- $
(ip
-o route get to
"$1")
808 while [ $# -gt 0 ]; do
823 # quote periods in IPv4 address
826 |
sed -n 's%^.* '"$qtd"' peer \([0-9a-f.:]\{1,\}\(/[0-9]*\)\?\).*$%\1%p'
833 # quote periods in IPv4 address
835 ip
-o addr show |
sed -n 's,^.* '"$qtd"'/\([0-9]*\) .*$,\1,p'
838 gateway_for_iface
() {
839 local ifname
=$1 addr
=$2
846 ip
-o -$proto route show \
847 |
sed -n "s/^default via \([0-9a-z.:]\{1,\}\) dev $ifname .*\$/\1/p"
850 # This works only for ifcfg-style network configuration!
851 bootproto_for_iface
() {
855 # follow ifcfg settings for boot protocol
856 for dir
in network-scripts network
; do
857 [ -f "/etc/sysconfig/$dir/ifcfg-$ifname" ] && {
858 sed -n "s/BOOTPROTO=[\"']\?\([[:alnum:]]\{1,\}\)[\"']\?.*\$/\1/p" \
859 "/etc/sysconfig/$dir/ifcfg-$ifname"
865 is_unbracketed_ipv6_address
() {
866 strglob
"$1" '*:*' && ! strglob
"$1" '\[*:*\]'
869 # Create an ip= string to set up networking such that the given
870 # remote address can be reached
871 ip_params_for_remote_addr
() {
873 local ifname local_addr peer netmask gateway ifmac
875 [[ $remote_addr ]] ||
return 1
876 ifname
=$
(iface_for_remote_addr
"$remote_addr")
878 berror
"failed to determine interface to connect to $remote_addr"
882 # ifname clause to bind the interface name to a MAC address
883 if [ -d "/sys/class/net/$ifname/bonding" ]; then
884 dinfo
"Found bonded interface '${ifname}'. Make sure to provide an appropriate 'bond=' cmdline."
885 elif [ -e "/sys/class/net/$ifname/address" ]; then
886 ifmac
=$
(cat "/sys/class/net/$ifname/address")
887 [[ $ifmac ]] && printf 'ifname=%s:%s ' "${ifname}" "${ifmac}"
890 bootproto
=$
(bootproto_for_iface
"$ifname")
892 dhcp | dhcp6 | auto6
) ;;
900 derror
"bootproto \"$bootproto\" is unsupported by dracut, trying static configuration"
904 if [[ $bootproto ]]; then
905 printf 'ip=%s:%s ' "${ifname}" "${bootproto}"
907 local_addr
=$
(local_addr_for_remote_addr
"$remote_addr")
908 [[ $local_addr ]] ||
{
909 berror
"failed to determine local address to connect to $remote_addr"
912 peer
=$
(peer_for_addr
"$local_addr")
913 # Set peer or netmask, but not both
914 [[ $peer ]] || netmask
=$
(netmask_for_addr
"$local_addr")
915 gateway
=$
(gateway_for_iface
"$ifname" "$local_addr")
916 # Quote IPv6 addresses with brackets
917 is_unbracketed_ipv6_address
"$local_addr" && local_addr
="[$local_addr]"
918 is_unbracketed_ipv6_address
"$peer" && peer
="[$peer]"
919 is_unbracketed_ipv6_address
"$gateway" && gateway
="[$gateway]"
920 printf 'ip=%s:%s:%s:%s::%s:none ' \
921 "${local_addr}" "${peer}" "${gateway}" "${netmask}" "${ifname}"
926 # block_is_nbd <maj:min>
927 # Check whether $1 is an nbd device
929 [[ -b /dev
/block
/$1 && $1 == 43:* ]]
932 # block_is_iscsi <maj:min>
933 # Check whether $1 is an iSCSI device
937 [[ -L "/sys/dev/block/$_dev" ]] ||
return
938 _dir
="$(readlink -f "/sys
/dev
/block
/$_dev")" ||
return
939 until [[ -d "$_dir/sys" ||
-d "$_dir/iscsi_session" ]]; do
942 [[ -d "$_dir/iscsi_session" ]]
945 # block_is_fcoe <maj:min>
946 # Check whether $1 is an FCoE device
947 # Will not work for HBAs that hide the ethernet aspect
948 # completely and present a pure FC device
952 [[ -L "/sys/dev/block/$_dev" ]] ||
return
953 _dir
="$(readlink -f "/sys
/dev
/block
/$_dev")"
954 until [[ -d "$_dir/sys" ]]; do
956 if [[ -d "$_dir/subsystem" ]]; then
957 subsystem
=$
(basename "$(readlink "$_dir"/subsystem)")
958 [[ $subsystem == "fcoe" ]] && return 0
964 # block_is_netdevice <maj:min>
965 # Check whether $1 is a net device
966 block_is_netdevice
() {
967 block_is_nbd
"$1" || block_is_iscsi
"$1" || block_is_fcoe
"$1"
970 # get the corresponding kernel modules of a /sys/class/*/* or/dev/* device
974 dev_attr_walk
=$
(udevadm info
-a "$1")
975 dev_drivers
=$
(echo "$dev_attr_walk" |
sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p')
976 # if no kernel modules found and device is in a virtual subsystem, follow symlinks
977 if [[ -z $dev_drivers && $
(udevadm info
-q path
"$1") == "/devices/virtual"* ]]; then
981 dev_vkernel
=$
(echo "$dev_attr_walk" |
sed -n 's/\s*KERNELS=="\(\S\+\)"/\1/p' |
tail -1)
982 dev_vsubsystem
=$
(echo "$dev_attr_walk" |
sed -n 's/\s*SUBSYSTEMS=="\(\S\+\)"/\1/p' |
tail -1)
983 dev_vpath
="/sys/devices/virtual/$dev_vsubsystem/$dev_vkernel"
984 if [[ -n $dev_vkernel && -n $dev_vsubsystem && -d $dev_vpath ]]; then
987 dev_links
=$
(find "$dev_vpath" -maxdepth 1 -type l
! -name "subsystem" -exec readlink
{} \
;)
988 for dev_link
in $dev_links; do
989 [[ -n $dev_drivers && ${dev_drivers: -1} != $
'\n' ]] && dev_drivers
+=$
'\n'
990 dev_drivers
+=$
(udevadm info
-a "$dev_vpath/$dev_link" \
991 |
sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p' \
992 |
grep -v -e pcieport
)