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" ]; }
42 var
="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
43 var
="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters
47 # find a binary. If we were not passed the full path directly,
48 # search in the usual places to find the binary.
54 [[ -z ${1##/*} ]] || _delim
="/"
56 if [[ $1 == *.so
* ]]; then
57 # shellcheck disable=SC2154
59 _path
="${l}${_delim}${1}"
60 if { $DRACUT_LDD "${dracutsysrootdir}${_path}" &> /dev/null; }; then
61 printf "%s
\n" "${_path}"
66 if { $DRACUT_LDD "${dracutsysrootdir}${_path}" &> /dev/null; }; then
67 printf "%s\n" "${_path}"
71 if [[ $1 == */* ]]; then
73 if [[ -L ${dracutsysrootdir}${_path} ]] || [[ -x ${dracutsysrootdir}${_path} ]]; then
74 printf "%s\n" "${_path}"
78 for p
in $DRACUT_PATH; do
79 _path
="${p}${_delim}${1}"
80 if [[ -L ${dracutsysrootdir}${_path} ]] || [[ -x ${dracutsysrootdir}${_path} ]]; then
81 printf "%s\n" "${_path}"
86 [[ -n $dracutsysrootdir ]] && return 1
91 $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
94 # Version comparision function. Assumes Linux style version scheme.
96 # $2 = comparision op (gt, ge, eq, le, lt, ne)
100 read -r -a _n1
<<< "${1//./ }"
103 read -r -a _n2
<<< "${3//./ }"
106 for ((_i
= 0; ; _i
++)); do
107 if [[ ! ${_n1[_i]}${_n2[_i]} ]]; then
109 elif ((${_n1[_i]:-0} > ${_n2[_i]:-0})); then
111 elif ((${_n1[_i]:-0} < ${_n2[_i]:-0})); then
129 # Create all subdirectories for given path without creating the last element.
132 # shellcheck disable=SC2174
133 [[ -e ${1%/*} ]] || mkdir
-m 0755 -p -- "${1%/*}"
136 # Function prints global variables in format name=value line by line.
137 # $@ = list of global variables' name
142 eval printf -v _value
"%s" \""\$$_var"\"
143 [[ ${_value} ]] && printf '%s="%s"\n' "$_var" "$_value"
147 # normalize_path <path>
148 # Prints the normalized path, where it removes any duplicated
149 # and trailing slashes.
151 # $ normalize_path ///test/test//
154 # shellcheck disable=SC2064
155 trap "$(shopt -p extglob)" RETURN
157 local p
=${1//+(\/)//}
158 printf "%s\n" "${p%/}"
161 # convert_abs_rel <from> <to>
162 # Prints the relative path, when creating a symlink to <to> from <from>.
164 # $ convert_abs_rel /usr/bin/test /bin/test-2
166 # $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
168 local __current __absolute __abssize __cursize __newpath
171 set -- "$(normalize_path "$1")" "$(normalize_path "$2")"
173 # corner case #1 - self looping link
174 [[ $1 == "$2" ]] && {
175 printf "%s\n" "${1##*/}"
179 # corner case #2 - own dir link
180 [[ ${1%/*} == "$2" ]] && {
185 IFS
=/ read -r -a __current
<<< "$1"
186 IFS
=/ read -r -a __absolute
<<< "$2"
188 __abssize
=${#__absolute[@]}
189 __cursize
=${#__current[@]}
191 while [[ ${__absolute[__level]} == "${__current[__level]}" ]]; do
193 if ((__level
> __abssize || __level
> __cursize
)); then
198 for ((__i
= __level
; __i
< __cursize
- 1; __i
++)); do
199 if ((__i
> __level
)); then
200 __newpath
=$__newpath"/"
202 __newpath
=$__newpath".."
205 for ((__i
= __level
; __i
< __abssize
; __i
++)); do
206 if [[ -n $__newpath ]]; then
207 __newpath
=$__newpath"/"
209 __newpath
=$__newpath${__absolute[__i]}
212 printf -- "%s\n" "$__newpath"
215 # get_fs_env <device>
216 # Get and the ID_FS_TYPE variable from udev for a device.
218 # $ get_fs_env /dev/sda2
223 ID_FS_TYPE
=$
(blkid
-u filesystem
-o export -- "$1" \
224 |
while read -r line ||
[ -n "$line" ]; do
225 if [[ $line == "TYPE="* ]]; then
226 printf "%s" "${line#TYPE=}"
230 if [[ $ID_FS_TYPE ]]; then
231 printf "%s" "$ID_FS_TYPE"
237 # get_maj_min <device>
238 # Prints the major and minor of a device node.
240 # $ get_maj_min /dev/sda2
246 if [[ $get_maj_min_cache_file ]]; then
247 _out
="$(grep -m1 -oE "^
$1 \S
+$
" "$get_maj_min_cache_file" | awk '{print $NF}')"
250 if ! [[ "$_out" ]]; then
251 _majmin
="$(stat -L -c '%t:%T' "$1" 2> /dev/null)"
252 _out
="$(printf "%s
" "$
((0x
${_majmin%:*})):$
((0x
${_majmin#*:}))")"
253 if [[ $get_maj_min_cache_file ]]; then
254 echo "$1 $_out" >> "$get_maj_min_cache_file"
260 # get_devpath_block <device>
261 # get the DEVPATH in /sys of a block device
262 get_devpath_block
() {
264 _majmin
=$
(get_maj_min
"$1")
266 for _i
in /sys
/block
/*/dev
/sys
/block
/*/*/dev
; do
267 [[ -e $_i ]] ||
continue
268 if [[ $_majmin == "$(< "$_i")" ]]; then
269 printf "%s" "${_i%/dev}"
276 # get a persistent path from a device
277 get_persistent_dev
() {
278 local i _tmp _dev _pol
280 _dev
=$
(get_maj_min
"$1")
281 [ -z "$_dev" ] && return
283 if [[ -n $persistent_policy ]]; then
284 _pol
="/dev/disk/${persistent_policy}/*"
292 /dev
/disk
/by-uuid
/* \
293 /dev
/disk
/by-label
/* \
294 /dev
/disk
/by-partuuid
/* \
295 /dev
/disk
/by-partlabel
/* \
297 /dev
/disk
/by-path
/*; do
298 [[ -e $i ]] ||
continue
299 [[ $i == /dev
/mapper
/control
]] && continue
300 [[ $i == /dev
/mapper
/mpath
* ]] && continue
301 _tmp
=$
(get_maj_min
"$i")
302 if [ "$_tmp" = "$_dev" ]; then
310 expand_persistent_dev
() {
315 _dev
="/dev/disk/by-label/${_dev#LABEL=}"
320 _dev
="/dev/disk/by-uuid/${_dev}"
323 _dev
="${_dev#PARTUUID=}"
325 _dev
="/dev/disk/by-partuuid/${_dev}"
328 _dev
="/dev/disk/by-partlabel/${_dev#PARTLABEL=}"
334 shorten_persistent_dev
() {
338 printf "%s" "UUID=${_dev##*/}"
340 /dev
/disk
/by-label
/*)
341 printf "%s" "LABEL=${_dev##*/}"
343 /dev
/disk
/by-partuuid
/*)
344 printf "%s" "PARTUUID=${_dev##*/}"
346 /dev
/disk
/by-partlabel
/*)
347 printf "%s" "PARTLABEL=${_dev##*/}"
355 # find_block_device <mountpoint>
356 # Prints the major and minor number of the block device
357 # for a given mountpoint.
358 # Unless $use_fstab is set to "yes" the functions
359 # uses /proc/self/mountinfo as the primary source of the
360 # information and only falls back to /etc/fstab, if the mountpoint
361 # is not found there.
363 # $ find_block_device /usr
365 find_block_device
() {
366 local _dev _majmin _find_mpt
369 if [[ $use_fstab != yes ]]; then
370 [[ -d $_find_mpt/.
]]
371 findmnt
-e -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" |
{
372 while read -r _majmin _dev ||
[ -n "$_dev" ]; do
373 if [[ -b $_dev ]]; then
374 if ! [[ $_majmin ]] ||
[[ $_majmin == 0:* ]]; then
375 _majmin
=$
(get_maj_min
"$_dev")
377 if [[ $_majmin ]]; then
378 printf "%s\n" "$_majmin"
380 printf "%s\n" "$_dev"
384 if [[ $_dev == *:* ]]; then
385 printf "%s\n" "$_dev"
392 # fall back to /etc/fstab
393 [[ ! -f "$dracutsysrootdir"/etc
/fstab
]] && return 1
395 findmnt
-e --fstab -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" |
{
396 while read -r _majmin _dev ||
[ -n "$_dev" ]; do
397 if ! [[ $_dev ]]; then
401 if [[ -b $_dev ]]; then
402 [[ $_majmin ]] || _majmin
=$
(get_maj_min
"$_dev")
403 if [[ $_majmin ]]; then
404 printf "%s\n" "$_majmin"
406 printf "%s\n" "$_dev"
410 if [[ $_dev == *:* ]]; then
411 printf "%s\n" "$_dev"
421 # find_mp_fstype <mountpoint>
422 # Echo the filesystem type for a given mountpoint.
423 # /proc/self/mountinfo is taken as the primary source of information
424 # and /etc/fstab is used as a fallback.
425 # No newline is appended!
427 # $ find_mp_fstype /;echo
432 if [[ $use_fstab != yes ]]; then
433 findmnt
-e -v -n -o 'FSTYPE' --target "$1" |
{
434 while read -r _fs ||
[ -n "$_fs" ]; do
435 [[ $_fs ]] ||
continue
436 [[ $_fs == "autofs" ]] && continue
444 [[ ! -f "$dracutsysrootdir"/etc
/fstab
]] && return 1
446 findmnt
--fstab -e -v -n -o 'FSTYPE' --target "$1" |
{
447 while read -r _fs ||
[ -n "$_fs" ]; do
448 [[ $_fs ]] ||
continue
449 [[ $_fs == "autofs" ]] && continue
459 # find_dev_fstype <device>
460 # Echo the filesystem type for a given device.
461 # /proc/self/mountinfo is taken as the primary source of information
462 # and /etc/fstab is used as a fallback.
463 # No newline is appended!
465 # $ find_dev_fstype /dev/sda2;echo
470 if ! [[ $_find_dev == /dev
* ]]; then
471 [[ -b "/dev/block/$_find_dev" ]] && _find_dev
="/dev/block/$_find_dev"
474 if [[ $use_fstab != yes ]]; then
475 findmnt
-e -v -n -o 'FSTYPE' --source "$_find_dev" |
{
476 while read -r _fs ||
[ -n "$_fs" ]; do
477 [[ $_fs ]] ||
continue
478 [[ $_fs == "autofs" ]] && continue
486 [[ ! -f "$dracutsysrootdir"/etc
/fstab
]] && return 1
488 findmnt
--fstab -e -v -n -o 'FSTYPE' --source "$_find_dev" |
{
489 while read -r _fs ||
[ -n "$_fs" ]; do
490 [[ $_fs ]] ||
continue
491 [[ $_fs == "autofs" ]] && continue
501 # find_mp_fsopts <mountpoint>
502 # Echo the filesystem options for a given mountpoint.
503 # /proc/self/mountinfo is taken as the primary source of information
504 # and /etc/fstab is used as a fallback.
505 # No newline is appended!
507 # $ find_mp_fsopts /;echo
508 # rw,relatime,discard,data=ordered
510 if [[ $use_fstab != yes ]]; then
511 findmnt
-e -v -n -o 'OPTIONS' --target "$1" 2> /dev
/null
&& return 0
514 [[ ! -f "$dracutsysrootdir"/etc
/fstab
]] && return 1
516 findmnt
--fstab -e -v -n -o 'OPTIONS' --target "$1"
519 # find_dev_fsopts <device>
520 # Echo the filesystem options for a given device.
521 # /proc/self/mountinfo is taken as the primary source of information
522 # and /etc/fstab is used as a fallback.
523 # if `use_fstab == yes`, then only `/etc/fstab` is used.
526 # $ find_dev_fsopts /dev/sda2
527 # rw,relatime,discard,data=ordered
531 if ! [[ $_find_dev == /dev
* ]]; then
532 [[ -b "/dev/block/$_find_dev" ]] && _find_dev
="/dev/block/$_find_dev"
535 if [[ $use_fstab != yes ]]; then
536 findmnt
-e -v -n -o 'OPTIONS' --source "$_find_dev" 2> /dev
/null
&& return 0
539 [[ ! -f "$dracutsysrootdir"/etc
/fstab
]] && return 1
541 findmnt
--fstab -e -v -n -o 'OPTIONS' --source "$_find_dev"
544 # finds the major:minor of the block device backing the root filesystem.
545 find_root_block_device
() { find_block_device
/; }
547 # for_each_host_dev_fs <func>
548 # Execute "<func> <dev> <filesystem>" for every "<dev> <fs>" pair found
549 # in ${host_fs_types[@]}
550 for_each_host_dev_fs
() {
555 [[ "${#host_fs_types[@]}" ]] ||
return 2
557 for _dev
in "${!host_fs_types[@]}"; do
558 $_func "$_dev" "${host_fs_types[$_dev]}" && _ret
=0
564 printf "%s\n" "${host_fs_types[@]}"
567 # Walk all the slave relationships for a given block device.
568 # Stop when our helper function returns success
569 # $1 = function to call on every found block device
570 # $2 = block device in major:minor format
571 check_block_and_slaves
() {
573 [[ -b /dev
/block
/$2 ]] ||
return 1 # Not a block device? So sorry.
574 if ! lvm_internal_dev
"$2"; then "$1" "$2" && return; fi
575 check_vol_slaves
"$@" && return 0
576 if [[ -f /sys
/dev
/block
/$2/..
/dev
]] && [[ /sys
/dev
/block
/$2/..
/subsystem
-ef /sys
/class
/block
]]; then
577 check_block_and_slaves
"$1" "$(< "/sys
/dev
/block
/$2/..
/dev
")" && return 0
579 for _x
in /sys
/dev
/block
/"$2"/slaves
/*; do
580 [[ -f $_x/dev
]] ||
continue
581 [[ $_x/subsystem
-ef /sys
/class
/block
]] ||
continue
582 check_block_and_slaves
"$1" "$(< "$_x/dev
")" && return 0
587 check_block_and_slaves_all
() {
589 [[ -b /dev
/block
/$2 ]] ||
return 1 # Not a block device? So sorry.
590 if ! lvm_internal_dev
"$2" && "$1" "$2"; then
593 check_vol_slaves_all
"$@" && return 0
594 if [[ -f /sys
/dev
/block
/$2/..
/dev
]] && [[ /sys
/dev
/block
/$2/..
/subsystem
-ef /sys
/class
/block
]]; then
595 check_block_and_slaves_all
"$1" "$(< "/sys
/dev
/block
/$2/..
/dev
")" && _ret
=0
597 for _x
in /sys
/dev
/block
/"$2"/slaves
/*; do
598 [[ -f $_x/dev
]] ||
continue
599 [[ $_x/subsystem
-ef /sys
/class
/block
]] ||
continue
600 check_block_and_slaves_all
"$1" "$(< "$_x/dev
")" && _ret
=0
604 # for_each_host_dev_and_slaves <func>
605 # Execute "<func> <dev>" for every "<dev>" found
606 # in ${host_devs[@]} and their slaves
607 for_each_host_dev_and_slaves_all
() {
612 [[ "${host_devs[*]}" ]] ||
return 2
614 for _dev
in "${host_devs[@]}"; do
615 [[ -b $_dev ]] ||
continue
616 if check_block_and_slaves_all
"$_func" "$(get_maj_min "$_dev")"; then
623 for_each_host_dev_and_slaves
() {
627 [[ "${host_devs[*]}" ]] ||
return 2
629 for _dev
in "${host_devs[@]}"; do
630 [[ -b $_dev ]] ||
continue
631 check_block_and_slaves
"$_func" "$(get_maj_min "$_dev")" && return 0
636 # /sys/dev/block/major:minor is symbol link to real hardware device
637 # go downstream $(realpath /sys/dev/block/major:minor) to detect driver
638 get_blockdev_drv_through_sys
() {
642 _path
=$
(realpath
"$1")
644 if [[ -L "$_path"/driver
/module
]]; then
645 _mod
=$
(realpath
"$_path"/driver
/module
)
646 _mod
=$
(basename "$_mod")
647 _block_mods
="$_block_mods $_mod"
649 _path
=$
(dirname "$_path")
650 if [[ $_path == '/sys/devices' ]] ||
[[ $_path == '/' ]]; then
657 # ugly workaround for the lvm design
658 # There is no volume group device,
659 # so, there are no slave devices for volume groups.
660 # Logical volumes only have the slave devices they really live on,
661 # but you cannot create the logical volume without the volume group.
662 # And the volume group might be bigger than the devices the LV needs.
664 local _vg _pv _dm _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 for _pv
in $
(lvm vgs
--noheadings -o pv_name
"$_vg" 2> /dev
/null
); do
673 check_block_and_slaves
"$1" "$(get_maj_min "$_pv")" && return 0
679 check_vol_slaves_all
() {
680 local _vg _pv _majmin
682 _dm
="/sys/dev/block/$_majmin/dm"
683 [[ -f $_dm/uuid
&& $
(< "$_dm"/uuid
) =~ LVM-
* ]] ||
return 1
684 _vg
=$
(dmsetup splitname
--noheadings -o vg_name
"$(< "$_dm/name
")")
686 _vg
="${_vg//[[:space:]]/}"
688 # when filter/global_filter is set, lvm may be failed
689 if ! lvm lvs
--noheadings -o vg_name
"$_vg" 2> /dev
/null
1> /dev
/null
; then
693 for _pv
in $
(lvm vgs
--noheadings -o pv_name
"$_vg" 2> /dev
/null
); do
694 check_block_and_slaves_all
"$1" "$(get_maj_min "$_pv")"
701 # fs_get_option <filesystem options> <search for option>
702 # search for a specific option in a bunch of filesystem options
703 # and return the value
709 # shellcheck disable=SC2086
712 while [ $# -gt 0 ]; do
715 echo "${1#"${_option}"=}"
723 check_kernel_config
() {
724 local _config_opt
="$1"
726 [[ -f $dracutsysrootdir/boot
/config-
$kernel ]] \
727 && _config_file
="/boot/config-$kernel"
728 [[ -f $dracutsysrootdir/lib
/modules
/$kernel/config
]] \
729 && _config_file
="/lib/modules/$kernel/config"
731 # no kernel config file, so return true
732 [[ $_config_file ]] ||
return 0
734 grep -q -F "${_config_opt}=" "$dracutsysrootdir$_config_file" && return 0
738 # 0 if the kernel module is either built-in or available
739 # 1 if the kernel module is not enabled
740 check_kernel_module
() {
741 modprobe
-d "$dracutsysrootdir" -S "$kernel" --dry-run "$1" &> /dev
/null ||
return 1
745 # Only two values are returned: AMD or Intel
747 if grep -qE AMD
/proc
/cpuinfo
; then
750 if grep -qE Intel
/proc
/cpuinfo
; then
756 # Get the hosts' ucode file based on the /proc/cpuinfo
761 family
=$
(grep -E "cpu family" /proc
/cpuinfo |
head -1 |
sed "s/.*:\ //")
762 model
=$
(grep -E "model" /proc
/cpuinfo |
grep -v name |
head -1 |
sed "s/.*:\ //")
763 stepping
=$
(grep -E "stepping" /proc
/cpuinfo |
head -1 |
sed "s/.*:\ //")
765 if [[ "$(get_cpu_vendor)" == "AMD" ]]; then
766 if [[ $family -ge 21 ]]; then
767 printf "microcode_amd_fam%xh.bin" "$family"
769 printf "microcode_amd.bin"
772 if [[ "$(get_cpu_vendor)" == "Intel" ]]; then
773 # The /proc/cpuinfo are in decimal.
774 printf "%02x-%02x-%02x" "${family}" "${model}" "${stepping}"
778 # Not every device in /dev/mapper should be examined.
779 # If it is an LVM device, touch only devices which have /dev/VG/LV symlink.
781 local dev_dm_dir
=/sys
/dev
/block
/$1/dm
782 [[ ! -f $dev_dm_dir/uuid || $
(< "$dev_dm_dir"/uuid
) != LVM-
* ]] && return 1 # Not an LVM device
783 local DM_VG_NAME DM_LV_NAME DM_LV_LAYER
784 eval "$(dmsetup splitname --nameprefixes --noheadings --rows "$
(< "$dev_dm_dir"/name
)" 2> /dev/null)"
785 [[ ${DM_VG_NAME} ]] && [[ ${DM_LV_NAME} ]] ||
return 0 # Better skip this!
786 [[ ${DM_LV_LAYER} ]] || [[ ! -L /dev/${DM_VG_NAME}/${DM_LV_NAME} ]]
791 btrfs device usage
"$_mp" \
792 |
while read -r _dev _
; do
793 str_starts
"$_dev" "/" ||
continue
795 printf -- "%s\n" "$_dev"
801 zpool list
-H -v -P "${_mp%%/*}" |
awk -F$
'\t' '$2 ~ /^\// {print $2}' \
802 |
while read -r _dev
; do
807 iface_for_remote_addr
() {
808 # shellcheck disable=SC2046
809 set -- $
(ip
-o route get to
"$1")
810 while [ $# -gt 0 ]; do
821 local_addr_for_remote_addr
() {
822 # shellcheck disable=SC2046
823 set -- $
(ip
-o route get to
"$1")
824 while [ $# -gt 0 ]; do
839 # quote periods in IPv4 address
842 |
sed -n 's%^.* '"$qtd"' peer \([0-9a-f.:]\{1,\}\(/[0-9]*\)\?\).*$%\1%p'
849 # quote periods in IPv4 address
851 ip
-o addr show |
sed -n 's,^.* '"$qtd"'/\([0-9]*\) .*$,\1,p'
854 gateway_for_iface
() {
855 local ifname
=$1 addr
=$2
862 ip
-o -$proto route show \
863 |
sed -n "s/^default via \([0-9a-z.:]\{1,\}\) dev $ifname .*\$/\1/p"
866 # This works only for ifcfg-style network configuration!
867 bootproto_for_iface
() {
871 # follow ifcfg settings for boot protocol
872 for dir
in network-scripts network
; do
873 [ -f "/etc/sysconfig/$dir/ifcfg-$ifname" ] && {
874 sed -n "s/BOOTPROTO=[\"']\?\([[:alnum:]]\{1,\}\)[\"']\?.*\$/\1/p" \
875 "/etc/sysconfig/$dir/ifcfg-$ifname"
881 is_unbracketed_ipv6_address
() {
882 strglob
"$1" '*:*' && ! strglob
"$1" '\[*:*\]'
885 # Create an ip= string to set up networking such that the given
886 # remote address can be reached
887 ip_params_for_remote_addr
() {
889 local ifname local_addr peer netmask gateway ifmac
891 [[ $remote_addr ]] ||
return 1
892 ifname
=$
(iface_for_remote_addr
"$remote_addr")
894 berror
"failed to determine interface to connect to $remote_addr"
898 # ifname clause to bind the interface name to a MAC address
899 if [ -d "/sys/class/net/$ifname/bonding" ]; then
900 dinfo
"Found bonded interface '${ifname}'. Make sure to provide an appropriate 'bond=' cmdline."
901 elif [ -e "/sys/class/net/$ifname/address" ]; then
902 ifmac
=$
(cat "/sys/class/net/$ifname/address")
903 [[ $ifmac ]] && printf 'ifname=%s:%s ' "${ifname}" "${ifmac}"
906 bootproto
=$
(bootproto_for_iface
"$ifname")
908 dhcp | dhcp6 | auto6
) ;;
916 derror
"bootproto \"$bootproto\" is unsupported by dracut, trying static configuration"
920 if [[ $bootproto ]]; then
921 printf 'ip=%s:%s ' "${ifname}" "${bootproto}"
923 local_addr
=$
(local_addr_for_remote_addr
"$remote_addr")
924 [[ $local_addr ]] ||
{
925 berror
"failed to determine local address to connect to $remote_addr"
928 peer
=$
(peer_for_addr
"$local_addr")
929 # Set peer or netmask, but not both
930 [[ $peer ]] || netmask
=$
(netmask_for_addr
"$local_addr")
931 gateway
=$
(gateway_for_iface
"$ifname" "$local_addr")
932 # Quote IPv6 addresses with brackets
933 is_unbracketed_ipv6_address
"$local_addr" && local_addr
="[$local_addr]"
934 is_unbracketed_ipv6_address
"$peer" && peer
="[$peer]"
935 is_unbracketed_ipv6_address
"$gateway" && gateway
="[$gateway]"
936 printf 'ip=%s:%s:%s:%s::%s:none ' \
937 "${local_addr}" "${peer}" "${gateway}" "${netmask}" "${ifname}"
942 # block_is_nbd <maj:min>
943 # Check whether $1 is an nbd device
945 [[ -b /dev
/block
/$1 && $1 == 43:* ]]
948 # block_is_iscsi <maj:min>
949 # Check whether $1 is an iSCSI device
953 [[ -L "/sys/dev/block/$_dev" ]] ||
return
954 _dir
="$(readlink -f "/sys
/dev
/block
/$_dev")" ||
return
955 until [[ -d "$_dir/sys" ||
-d "$_dir/iscsi_session" ]]; do
958 [[ -d "$_dir/iscsi_session" ]]
961 # block_is_fcoe <maj:min>
962 # Check whether $1 is an FCoE device
963 # Will not work for HBAs that hide the ethernet aspect
964 # completely and present a pure FC device
968 [[ -L "/sys/dev/block/$_dev" ]] ||
return
969 _dir
="$(readlink -f "/sys
/dev
/block
/$_dev")"
970 until [[ -d "$_dir/sys" ]]; do
972 if [[ -d "$_dir/subsystem" ]]; then
973 subsystem
=$
(basename "$(readlink "$_dir"/subsystem)")
974 [[ $subsystem == "fcoe" ]] && return 0
980 # block_is_netdevice <maj:min>
981 # Check whether $1 is a net device
982 block_is_netdevice
() {
983 block_is_nbd
"$1" || block_is_iscsi
"$1" || block_is_fcoe
"$1"
986 # convert the driver name given by udevadm to the corresponding kernel module name
989 while read -r dev_driver
; do
990 case "$dev_driver" in
1001 # get the corresponding kernel modules of a /sys/class/*/* or/dev/* device
1006 dev_attr_walk
=$
(udevadm info
-a "$1")
1007 dev_drivers
=$
(echo "$dev_attr_walk" \
1008 |
sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p' \
1011 # also return modalias info from sysfs paths parsed by udevadm
1012 dev_paths
=$
(echo "$dev_attr_walk" |
sed -n 's/.*\(\/devices\/.*\)'\'':/\1/p')
1014 for dev_path
in $dev_paths; do
1015 local modalias_file
="/sys$dev_path/modalias"
1016 if [ -e "$modalias_file" ]; then
1017 dev_drivers
="$(printf "%s
\n%s
" "$dev_drivers" "$
(cat "$modalias_file")")"
1021 # if no kernel modules found and device is in a virtual subsystem, follow symlinks
1022 if [[ -z $dev_drivers && $
(udevadm info
-q path
"$1") == "/devices/virtual"* ]]; then
1024 local dev_vsubsystem
1026 dev_vkernel
=$
(echo "$dev_attr_walk" |
sed -n 's/\s*KERNELS=="\(\S\+\)"/\1/p' |
tail -1)
1027 dev_vsubsystem
=$
(echo "$dev_attr_walk" |
sed -n 's/\s*SUBSYSTEMS=="\(\S\+\)"/\1/p' |
tail -1)
1028 dev_vpath
="/sys/devices/virtual/$dev_vsubsystem/$dev_vkernel"
1029 if [[ -n $dev_vkernel && -n $dev_vsubsystem && -d $dev_vpath ]]; then
1032 dev_links
=$
(find "$dev_vpath" -maxdepth 1 -type l
! -name "subsystem" -exec readlink
{} \
;)
1033 for dev_link
in $dev_links; do
1034 [[ -n $dev_drivers && ${dev_drivers: -1} != $
'\n' ]] && dev_drivers
+=$
'\n'
1035 dev_drivers
+=$
(udevadm info
-a "$dev_vpath/$dev_link" \
1036 |
sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p' \
1038 |
grep -v -e pcieport
)
1045 # Check if file is in PE format
1047 if [[ $# -eq 1 ]]; then
1049 magic
=$
(objdump
-p "$1" \
1050 |
awk '{if ($1 == "Magic"){print strtonum("0x"$2)}}')
1051 magic
=$
(printf "0x%x" "$magic")
1052 # 0x10b (PE32), 0x20b (PE32+)
1053 [[ $magic == 0x20b ||
$magic == 0x10b ]] && return 0
1058 # Get specific data from the PE header
1059 pe_get_header_data
() {
1061 [[ $# -ne "2" ]] && return 1
1062 [[ $
(pe_file_format
"$1") -eq 1 ]] && return 1
1063 data_header
=$
(objdump
-p "$1" \
1064 |
awk -v data
="$2" '{if ($1 == data){print $2}}')
1068 # Get the SectionAlignment data from the PE header
1069 pe_get_section_align
() {
1071 [[ $# -ne "1" ]] && return 1
1072 align_hex
=$
(pe_get_header_data
"$1" "SectionAlignment")
1073 [[ $?
-eq 1 ]] && return 1
1074 echo "$((16#$align_hex))"
1077 # Get the ImageBase data from the PE header
1078 pe_get_image_base
() {
1080 [[ $# -ne "1" ]] && return 1
1081 base_image
=$
(pe_get_header_data
"$1" "ImageBase")
1082 [[ $?
-eq 1 ]] && return 1
1083 echo "$((16#$base_image))"