]> git.ipfire.org Git - thirdparty/dracut.git/blob - dracut-functions.sh
test: use hosts randomness, not rngd
[thirdparty/dracut.git] / dracut-functions.sh
1 #!/bin/bash
2 #
3 # functions used by dracut and other tools.
4 #
5 # Copyright 2005-2009 Red Hat, Inc. All rights reserved.
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #
20 export LC_MESSAGES=C
21
22 # is_func <command>
23 # Check whether $1 is a function.
24 is_func() {
25 [[ "$(type -t "$1")" = "function" ]]
26 }
27
28
29 # Generic substring function. If $2 is in $1, return 0.
30 strstr() { [[ $1 = *"$2"* ]]; }
31 # Generic glob matching function. If glob pattern $2 matches anywhere in $1, OK
32 strglobin() { [[ $1 = *$2* ]]; }
33 # Generic glob matching function. If glob pattern $2 matches all of $1, OK
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" ]; }
39
40 # find a binary. If we were not passed the full path directly,
41 # search in the usual places to find the binary.
42 find_binary() {
43 local _delim
44 local l
45 local p
46 [[ -z ${1##/*} ]] || _delim="/"
47
48 if [[ "$1" == *.so* ]]; then
49 for l in libdirs ; do
50 if { $DRACUT_LDD "$dracutsysrootdir$l$_delim$1" &>/dev/null; }; then
51 printf "%s\n" "$1"
52 return 0
53 fi
54 done
55 if { $DRACUT_LDD "$dracutsysrootdir$_delim$1" &>/dev/null; }; then
56 printf "%s\n" "$1"
57 return 0
58 fi
59 fi
60 if [[ "$1" == */* ]]; then
61 if [[ -L $dracutsysrootdir$_delim$1 ]] || [[ -x $dracutsysrootdir$_delim$1 ]]; then
62 printf "%s\n" "$1"
63 return 0
64 fi
65 fi
66 for p in $DRACUT_PATH ; do
67 if [[ -L $dracutsysrootdir$p$_delim$1 ]] || [[ -x $dracutsysrootdir$p$_delim$1 ]]; then
68 printf "%s\n" "$1"
69 return 0
70 fi
71 done
72
73 [[ -n "$dracutsysrootdir" ]] && return 1
74 type -P "${1##*/}"
75 }
76
77 ldconfig_paths()
78 {
79 $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
80 }
81
82 # Version comparision function. Assumes Linux style version scheme.
83 # $1 = version a
84 # $2 = comparision op (gt, ge, eq, le, lt, ne)
85 # $3 = version b
86 vercmp() {
87 local _n1=(${1//./ }) _op=$2 _n2=(${3//./ }) _i _res
88
89 for ((_i=0; ; _i++))
90 do
91 if [[ ! ${_n1[_i]}${_n2[_i]} ]]; then _res=0
92 elif ((${_n1[_i]:-0} > ${_n2[_i]:-0})); then _res=1
93 elif ((${_n1[_i]:-0} < ${_n2[_i]:-0})); then _res=2
94 else continue
95 fi
96 break
97 done
98
99 case $_op in
100 gt) ((_res == 1));;
101 ge) ((_res != 2));;
102 eq) ((_res == 0));;
103 le) ((_res != 1));;
104 lt) ((_res == 2));;
105 ne) ((_res != 0));;
106 esac
107 }
108
109 # Create all subdirectories for given path without creating the last element.
110 # $1 = path
111 mksubdirs() {
112 [[ -e ${1%/*} ]] || mkdir -m 0755 -p -- "${1%/*}"
113 }
114
115 # Function prints global variables in format name=value line by line.
116 # $@ = list of global variables' name
117 print_vars() {
118 local _var _value
119
120 for _var in "$@"
121 do
122 eval printf -v _value "%s" \""\$$_var"\"
123 [[ ${_value} ]] && printf '%s="%s"\n' "$_var" "$_value"
124 done
125 }
126
127 # normalize_path <path>
128 # Prints the normalized path, where it removes any duplicated
129 # and trailing slashes.
130 # Example:
131 # $ normalize_path ///test/test//
132 # /test/test
133 normalize_path() {
134 shopt -q -s extglob
135 set -- "${1//+(\/)//}"
136 shopt -q -u extglob
137 printf "%s\n" "${1%/}"
138 }
139
140 # convert_abs_rel <from> <to>
141 # Prints the relative path, when creating a symlink to <to> from <from>.
142 # Example:
143 # $ convert_abs_rel /usr/bin/test /bin/test-2
144 # ../../bin/test-2
145 # $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
146 convert_abs_rel() {
147 local __current __absolute __abssize __cursize __newpath
148 local -i __i __level
149
150 set -- "$(normalize_path "$1")" "$(normalize_path "$2")"
151
152 # corner case #1 - self looping link
153 [[ "$1" == "$2" ]] && { printf "%s\n" "${1##*/}"; return; }
154
155 # corner case #2 - own dir link
156 [[ "${1%/*}" == "$2" ]] && { printf ".\n"; return; }
157
158 IFS="/" __current=($1)
159 IFS="/" __absolute=($2)
160
161 __abssize=${#__absolute[@]}
162 __cursize=${#__current[@]}
163
164 while [[ "${__absolute[__level]}" == "${__current[__level]}" ]]
165 do
166 (( __level++ ))
167 if (( __level > __abssize || __level > __cursize ))
168 then
169 break
170 fi
171 done
172
173 for ((__i = __level; __i < __cursize-1; __i++))
174 do
175 if ((__i > __level))
176 then
177 __newpath=$__newpath"/"
178 fi
179 __newpath=$__newpath".."
180 done
181
182 for ((__i = __level; __i < __abssize; __i++))
183 do
184 if [[ -n $__newpath ]]
185 then
186 __newpath=$__newpath"/"
187 fi
188 __newpath=$__newpath${__absolute[__i]}
189 done
190
191 printf "%s\n" "$__newpath"
192 }
193
194
195 # get_fs_env <device>
196 # Get and the ID_FS_TYPE variable from udev for a device.
197 # Example:
198 # $ get_fs_env /dev/sda2
199 # ext4
200 get_fs_env() {
201 [[ $1 ]] || return
202 unset ID_FS_TYPE
203 ID_FS_TYPE=$(blkid -u filesystem -o export -- "$1" \
204 | while read line || [ -n "$line" ]; do
205 if [[ "$line" == TYPE\=* ]]; then
206 printf "%s" "${line#TYPE=}";
207 exit 0;
208 fi
209 done)
210 if [[ $ID_FS_TYPE ]]; then
211 printf "%s" "$ID_FS_TYPE"
212 return 0
213 fi
214 return 1
215 }
216
217 # get_maj_min <device>
218 # Prints the major and minor of a device node.
219 # Example:
220 # $ get_maj_min /dev/sda2
221 # 8:2
222 get_maj_min() {
223 local _majmin
224 _majmin="$(stat -L -c '%t:%T' "$1" 2>/dev/null)"
225 printf "%s" "$((0x${_majmin%:*})):$((0x${_majmin#*:}))"
226 }
227
228
229 # get_devpath_block <device>
230 # get the DEVPATH in /sys of a block device
231 get_devpath_block() {
232 local _majmin _i
233 _majmin=$(get_maj_min "$1")
234
235 for _i in /sys/block/*/dev /sys/block/*/*/dev; do
236 [[ -e "$_i" ]] || continue
237 if [[ "$_majmin" == "$(<"$_i")" ]]; then
238 printf "%s" "${_i%/dev}"
239 return 0
240 fi
241 done
242 return 1
243 }
244
245 # get a persistent path from a device
246 get_persistent_dev() {
247 local i _tmp _dev _pol
248
249 _dev=$(get_maj_min "$1")
250 [ -z "$_dev" ] && return
251
252 if [[ -n "$persistent_policy" ]]; then
253 _pol="/dev/disk/${persistent_policy}/*"
254 else
255 _pol=
256 fi
257
258 for i in \
259 $_pol \
260 /dev/mapper/* \
261 /dev/disk/by-uuid/* \
262 /dev/disk/by-label/* \
263 /dev/disk/by-partuuid/* \
264 /dev/disk/by-partlabel/* \
265 /dev/disk/by-id/* \
266 /dev/disk/by-path/* \
267 ; do
268 [[ -e "$i" ]] || continue
269 [[ $i == /dev/mapper/control ]] && continue
270 [[ $i == /dev/mapper/mpath* ]] && continue
271 _tmp=$(get_maj_min "$i")
272 if [ "$_tmp" = "$_dev" ]; then
273 printf -- "%s" "$i"
274 return
275 fi
276 done
277 printf -- "%s" "$1"
278 }
279
280 expand_persistent_dev() {
281 local _dev=$1
282
283 case "$_dev" in
284 LABEL=*)
285 _dev="/dev/disk/by-label/${_dev#LABEL=}"
286 ;;
287 UUID=*)
288 _dev="${_dev#UUID=}"
289 _dev="${_dev,,}"
290 _dev="/dev/disk/by-uuid/${_dev}"
291 ;;
292 PARTUUID=*)
293 _dev="${_dev#PARTUUID=}"
294 _dev="${_dev,,}"
295 _dev="/dev/disk/by-partuuid/${_dev}"
296 ;;
297 PARTLABEL=*)
298 _dev="/dev/disk/by-partlabel/${_dev#PARTLABEL=}"
299 ;;
300 esac
301 printf "%s" "$_dev"
302 }
303
304 shorten_persistent_dev() {
305 local _dev="$1"
306 case "$_dev" in
307 /dev/disk/by-uuid/*)
308 printf "%s" "UUID=${_dev##*/}";;
309 /dev/disk/by-label/*)
310 printf "%s" "LABEL=${_dev##*/}";;
311 /dev/disk/by-partuuid/*)
312 printf "%s" "PARTUUID=${_dev##*/}";;
313 /dev/disk/by-partlabel/*)
314 printf "%s" "PARTLABEL=${_dev##*/}";;
315 *)
316 printf "%s" "$_dev";;
317 esac
318 }
319
320 # find_block_device <mountpoint>
321 # Prints the major and minor number of the block device
322 # for a given mountpoint.
323 # Unless $use_fstab is set to "yes" the functions
324 # uses /proc/self/mountinfo as the primary source of the
325 # information and only falls back to /etc/fstab, if the mountpoint
326 # is not found there.
327 # Example:
328 # $ find_block_device /usr
329 # 8:4
330 find_block_device() {
331 local _dev _majmin _find_mpt
332 _find_mpt="$1"
333 if [[ $use_fstab != yes ]]; then
334 [[ -d $_find_mpt/. ]]
335 findmnt -e -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" | { \
336 while read _majmin _dev || [ -n "$_dev" ]; do
337 if [[ -b $_dev ]]; then
338 if ! [[ $_majmin ]] || [[ $_majmin == 0:* ]]; then
339 _majmin=$(get_maj_min $_dev)
340 fi
341 if [[ $_majmin ]]; then
342 printf "%s\n" "$_majmin"
343 else
344 printf "%s\n" "$_dev"
345 fi
346 return 0
347 fi
348 if [[ $_dev = *:* ]]; then
349 printf "%s\n" "$_dev"
350 return 0
351 fi
352 done; return 1; } && return 0
353 fi
354 # fall back to /etc/fstab
355
356 findmnt -e --fstab -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" | { \
357 while read _majmin _dev || [ -n "$_dev" ]; do
358 if ! [[ $_dev ]]; then
359 _dev="$_majmin"
360 unset _majmin
361 fi
362 if [[ -b $_dev ]]; then
363 [[ $_majmin ]] || _majmin=$(get_maj_min $_dev)
364 if [[ $_majmin ]]; then
365 printf "%s\n" "$_majmin"
366 else
367 printf "%s\n" "$_dev"
368 fi
369 return 0
370 fi
371 if [[ $_dev = *:* ]]; then
372 printf "%s\n" "$_dev"
373 return 0
374 fi
375 done; return 1; } && return 0
376
377 return 1
378 }
379
380 # find_mp_fstype <mountpoint>
381 # Echo the filesystem type for a given mountpoint.
382 # /proc/self/mountinfo is taken as the primary source of information
383 # and /etc/fstab is used as a fallback.
384 # No newline is appended!
385 # Example:
386 # $ find_mp_fstype /;echo
387 # ext4
388 find_mp_fstype() {
389 local _fs
390
391 if [[ $use_fstab != yes ]]; then
392 findmnt -e -v -n -o 'FSTYPE' --target "$1" | { \
393 while read _fs || [ -n "$_fs" ]; do
394 [[ $_fs ]] || continue
395 [[ $_fs = "autofs" ]] && continue
396 printf "%s" "$_fs"
397 return 0
398 done; return 1; } && return 0
399 fi
400
401 findmnt --fstab -e -v -n -o 'FSTYPE' --target "$1" | { \
402 while read _fs || [ -n "$_fs" ]; do
403 [[ $_fs ]] || continue
404 [[ $_fs = "autofs" ]] && continue
405 printf "%s" "$_fs"
406 return 0
407 done; return 1; } && return 0
408
409 return 1
410 }
411
412 # find_dev_fstype <device>
413 # Echo the filesystem type for a given device.
414 # /proc/self/mountinfo is taken as the primary source of information
415 # and /etc/fstab is used as a fallback.
416 # No newline is appended!
417 # Example:
418 # $ find_dev_fstype /dev/sda2;echo
419 # ext4
420 find_dev_fstype() {
421 local _find_dev _fs
422 _find_dev="$1"
423 if ! [[ "$_find_dev" = /dev* ]]; then
424 [[ -b "/dev/block/$_find_dev" ]] && _find_dev="/dev/block/$_find_dev"
425 fi
426
427 if [[ $use_fstab != yes ]]; then
428 findmnt -e -v -n -o 'FSTYPE' --source "$_find_dev" | { \
429 while read _fs || [ -n "$_fs" ]; do
430 [[ $_fs ]] || continue
431 [[ $_fs = "autofs" ]] && continue
432 printf "%s" "$_fs"
433 return 0
434 done; return 1; } && return 0
435 fi
436
437 findmnt --fstab -e -v -n -o 'FSTYPE' --source "$_find_dev" | { \
438 while read _fs || [ -n "$_fs" ]; do
439 [[ $_fs ]] || continue
440 [[ $_fs = "autofs" ]] && continue
441 printf "%s" "$_fs"
442 return 0
443 done; return 1; } && return 0
444
445 return 1
446 }
447
448 # find_mp_fsopts <mountpoint>
449 # Echo the filesystem options for a given mountpoint.
450 # /proc/self/mountinfo is taken as the primary source of information
451 # and /etc/fstab is used as a fallback.
452 # No newline is appended!
453 # Example:
454 # $ find_mp_fsopts /;echo
455 # rw,relatime,discard,data=ordered
456 find_mp_fsopts() {
457 if [[ $use_fstab != yes ]]; then
458 findmnt -e -v -n -o 'OPTIONS' --target "$1" 2>/dev/null && return 0
459 fi
460
461 findmnt --fstab -e -v -n -o 'OPTIONS' --target "$1"
462 }
463
464 # find_dev_fsopts <device>
465 # Echo the filesystem options for a given device.
466 # /proc/self/mountinfo is taken as the primary source of information
467 # and /etc/fstab is used as a fallback.
468 # Example:
469 # $ find_dev_fsopts /dev/sda2
470 # rw,relatime,discard,data=ordered
471 find_dev_fsopts() {
472 local _find_dev _opts
473 _find_dev="$1"
474 if ! [[ "$_find_dev" = /dev* ]]; then
475 [[ -b "/dev/block/$_find_dev" ]] && _find_dev="/dev/block/$_find_dev"
476 fi
477
478 if [[ $use_fstab != yes ]]; then
479 findmnt -e -v -n -o 'OPTIONS' --source "$_find_dev" 2>/dev/null && return 0
480 fi
481
482 findmnt --fstab -e -v -n -o 'OPTIONS' --source "$_find_dev"
483 }
484
485
486 # finds the major:minor of the block device backing the root filesystem.
487 find_root_block_device() { find_block_device /; }
488
489 # for_each_host_dev_fs <func>
490 # Execute "<func> <dev> <filesystem>" for every "<dev> <fs>" pair found
491 # in ${host_fs_types[@]}
492 for_each_host_dev_fs()
493 {
494 local _func="$1"
495 local _dev
496 local _ret=1
497
498 [[ "${#host_fs_types[@]}" ]] || return 2
499
500
501 for _dev in "${!host_fs_types[@]}"; do
502 $_func "$_dev" "${host_fs_types[$_dev]}" && _ret=0
503 done
504 return $_ret
505 }
506
507 host_fs_all()
508 {
509 printf "%s\n" "${host_fs_types[@]}"
510 }
511
512 # Walk all the slave relationships for a given block device.
513 # Stop when our helper function returns success
514 # $1 = function to call on every found block device
515 # $2 = block device in major:minor format
516 check_block_and_slaves() {
517 local _x
518 [[ -b /dev/block/$2 ]] || return 1 # Not a block device? So sorry.
519 if ! lvm_internal_dev $2; then "$1" $2 && return; fi
520 check_vol_slaves "$@" && return 0
521 if [[ -f /sys/dev/block/$2/../dev ]] && [[ /sys/dev/block/$2/../subsystem -ef /sys/class/block ]]; then
522 check_block_and_slaves $1 $(<"/sys/dev/block/$2/../dev") && return 0
523 fi
524 [[ -d /sys/dev/block/$2/slaves ]] || return 1
525 for _x in /sys/dev/block/$2/slaves/*; do
526 [[ -f $_x/dev ]] || continue
527 [[ $_x/subsystem -ef /sys/class/block ]] || continue
528 check_block_and_slaves $1 $(<"$_x/dev") && return 0
529 done
530 return 1
531 }
532
533 check_block_and_slaves_all() {
534 local _x _ret=1
535 [[ -b /dev/block/$2 ]] || return 1 # Not a block device? So sorry.
536 if ! lvm_internal_dev $2 && "$1" $2; then
537 _ret=0
538 fi
539 check_vol_slaves_all "$@" && return 0
540 if [[ -f /sys/dev/block/$2/../dev ]] && [[ /sys/dev/block/$2/../subsystem -ef /sys/class/block ]]; then
541 check_block_and_slaves_all $1 $(<"/sys/dev/block/$2/../dev") && _ret=0
542 fi
543 [[ -d /sys/dev/block/$2/slaves ]] || return 1
544 for _x in /sys/dev/block/$2/slaves/*; do
545 [[ -f $_x/dev ]] || continue
546 [[ $_x/subsystem -ef /sys/class/block ]] || continue
547 check_block_and_slaves_all $1 $(<"$_x/dev") && _ret=0
548 done
549 return $_ret
550 }
551 # for_each_host_dev_and_slaves <func>
552 # Execute "<func> <dev>" for every "<dev>" found
553 # in ${host_devs[@]} and their slaves
554 for_each_host_dev_and_slaves_all()
555 {
556 local _func="$1"
557 local _dev
558 local _ret=1
559
560 [[ "${host_devs[@]}" ]] || return 2
561
562 for _dev in "${host_devs[@]}"; do
563 [[ -b "$_dev" ]] || continue
564 if check_block_and_slaves_all $_func $(get_maj_min $_dev); then
565 _ret=0
566 fi
567 done
568 return $_ret
569 }
570
571 for_each_host_dev_and_slaves()
572 {
573 local _func="$1"
574 local _dev
575
576 [[ "${host_devs[@]}" ]] || return 2
577
578 for _dev in "${host_devs[@]}"; do
579 [[ -b "$_dev" ]] || continue
580 check_block_and_slaves $_func $(get_maj_min $_dev) && return 0
581 done
582 return 1
583 }
584
585 # ugly workaround for the lvm design
586 # There is no volume group device,
587 # so, there are no slave devices for volume groups.
588 # Logical volumes only have the slave devices they really live on,
589 # but you cannot create the logical volume without the volume group.
590 # And the volume group might be bigger than the devices the LV needs.
591 check_vol_slaves() {
592 local _lv _vg _pv _dm _majmin
593 _majmin="$2"
594 _lv="/dev/block/$_majmin"
595 _dm=/sys/dev/block/$_majmin/dm
596 [[ -f $_dm/uuid && $(<$_dm/uuid) =~ LVM-* ]] || return 1
597 _vg=$(dmsetup splitname --noheadings -o vg_name $(<"$_dm/name") )
598 # strip space
599 _vg="${_vg//[[:space:]]/}"
600 if [[ $_vg ]]; then
601 for _pv in $(lvm vgs --noheadings -o pv_name "$_vg" 2>/dev/null)
602 do
603 check_block_and_slaves $1 $(get_maj_min $_pv) && return 0
604 done
605 fi
606 return 1
607 }
608
609 check_vol_slaves_all() {
610 local _lv _vg _pv _majmin
611 _majmin="$2"
612 _lv="/dev/block/$_majmin"
613 _dm="/sys/dev/block/$_majmin/dm"
614 [[ -f $_dm/uuid && $(<$_dm/uuid) =~ LVM-* ]] || return 1
615 _vg=$(dmsetup splitname --noheadings -o vg_name $(<"$_dm/name") )
616 # strip space
617 _vg="${_vg//[[:space:]]/}"
618 if [[ $_vg ]]; then
619 # when filter/global_filter is set, lvm may be failed
620 lvm lvs --noheadings -o vg_name $_vg 2>/dev/null 1>/dev/null
621 if [ $? -ne 0 ]; then
622 return 1
623 fi
624
625 for _pv in $(lvm vgs --noheadings -o pv_name "$_vg" 2>/dev/null)
626 do
627 check_block_and_slaves_all $1 $(get_maj_min $_pv)
628 done
629 return 0
630 fi
631 return 1
632 }
633
634
635
636 # fs_get_option <filesystem options> <search for option>
637 # search for a specific option in a bunch of filesystem options
638 # and return the value
639 fs_get_option() {
640 local _fsopts=$1
641 local _option=$2
642 local OLDIFS="$IFS"
643 IFS=,
644 set -- $_fsopts
645 IFS="$OLDIFS"
646 while [ $# -gt 0 ]; do
647 case $1 in
648 $_option=*)
649 echo ${1#${_option}=}
650 break
651 esac
652 shift
653 done
654 }
655
656 check_kernel_config()
657 {
658 local _config_opt="$1"
659 local _config_file
660 [[ -f $dracutsysrootdir/boot/config-$kernel ]] \
661 && _config_file="/boot/config-$kernel"
662 [[ -f $dracutsysrootdir/lib/modules/$kernel/config ]] \
663 && _config_file="/lib/modules/$kernel/config"
664
665 # no kernel config file, so return true
666 [[ $_config_file ]] || return 0
667
668 grep -q -F "${_config_opt}=" "$_config_file" && return 0
669 return 1
670 }
671
672
673 # get_cpu_vendor
674 # Only two values are returned: AMD or Intel
675 get_cpu_vendor ()
676 {
677 if grep -qE AMD /proc/cpuinfo; then
678 printf "AMD"
679 fi
680 if grep -qE Intel /proc/cpuinfo; then
681 printf "Intel"
682 fi
683 }
684
685 # get_host_ucode
686 # Get the hosts' ucode file based on the /proc/cpuinfo
687 get_ucode_file ()
688 {
689 local family=`grep -E "cpu family" /proc/cpuinfo | head -1 | sed s/.*:\ //`
690 local model=`grep -E "model" /proc/cpuinfo |grep -v name | head -1 | sed s/.*:\ //`
691 local stepping=`grep -E "stepping" /proc/cpuinfo | head -1 | sed s/.*:\ //`
692
693 if [[ "$(get_cpu_vendor)" == "AMD" ]]; then
694 if [[ $family -ge 21 ]]; then
695 printf "microcode_amd_fam%xh.bin" $family
696 else
697 printf "microcode_amd.bin"
698 fi
699 fi
700 if [[ "$(get_cpu_vendor)" == "Intel" ]]; then
701 # The /proc/cpuinfo are in decimal.
702 printf "%02x-%02x-%02x" ${family} ${model} ${stepping}
703 fi
704 }
705
706 # Not every device in /dev/mapper should be examined.
707 # If it is an LVM device, touch only devices which have /dev/VG/LV symlink.
708 lvm_internal_dev() {
709 local dev_dm_dir=/sys/dev/block/$1/dm
710 [[ ! -f $dev_dm_dir/uuid || $(<$dev_dm_dir/uuid) != LVM-* ]] && return 1 # Not an LVM device
711 local DM_VG_NAME DM_LV_NAME DM_LV_LAYER
712 eval $(dmsetup splitname --nameprefixes --noheadings --rows "$(<$dev_dm_dir/name)" 2>/dev/null)
713 [[ ${DM_VG_NAME} ]] && [[ ${DM_LV_NAME} ]] || return 0 # Better skip this!
714 [[ ${DM_LV_LAYER} ]] || [[ ! -L /dev/${DM_VG_NAME}/${DM_LV_NAME} ]]
715 }
716
717 btrfs_devs() {
718 local _mp="$1"
719 btrfs device usage "$_mp" \
720 | while read _dev _rest; do
721 str_starts "$_dev" "/" || continue
722 _dev=${_dev%,}
723 printf -- "%s\n" "$_dev"
724 done
725 }