]> git.ipfire.org Git - thirdparty/dracut.git/blobdiff - dracut-functions.sh
ci: run all local tests on all containers (including Gentoo)
[thirdparty/dracut.git] / dracut-functions.sh
index 8503c22f6a3f63ebbe2f3821e59b66af306ebda6..8afbbd801ed428225511a31141da7901b0038e39 100755 (executable)
@@ -37,6 +37,13 @@ str_starts() { [ "${1#"$2"*}" != "$1" ]; }
 # returns OK if $1 contains literal string $2 at the end, and isn't empty
 str_ends() { [ "${1%*"$2"}" != "$1" ]; }
 
+trim() {
+    local var="$*"
+    var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
+    var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters
+    printf "%s" "$var"
+}
+
 # find a binary.  If we were not passed the full path directly,
 # search in the usual places to find the binary.
 find_binary() {
@@ -237,7 +244,7 @@ get_maj_min() {
     local _out
 
     if [[ $get_maj_min_cache_file ]]; then
-        _out="$(grep -m1 -oP "^$1 \K\S+$" "$get_maj_min_cache_file")"
+        _out="$(grep -m1 -oE "^$1 \S+$" "$get_maj_min_cache_file" | awk '{print $NF}')"
     fi
 
     if ! [[ "$_out" ]]; then
@@ -383,6 +390,7 @@ find_block_device() {
         } && return 0
     fi
     # fall back to /etc/fstab
+    [[ ! -f "$dracutsysrootdir"/etc/fstab ]] && return 1
 
     findmnt -e --fstab -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" | {
         while read -r _majmin _dev || [ -n "$_dev" ]; do
@@ -433,6 +441,8 @@ find_mp_fstype() {
         } && return 0
     fi
 
+    [[ ! -f "$dracutsysrootdir"/etc/fstab ]] && return 1
+
     findmnt --fstab -e -v -n -o 'FSTYPE' --target "$1" | {
         while read -r _fs || [ -n "$_fs" ]; do
             [[ $_fs ]] || continue
@@ -473,6 +483,8 @@ find_dev_fstype() {
         } && return 0
     fi
 
+    [[ ! -f "$dracutsysrootdir"/etc/fstab ]] && return 1
+
     findmnt --fstab -e -v -n -o 'FSTYPE' --source "$_find_dev" | {
         while read -r _fs || [ -n "$_fs" ]; do
             [[ $_fs ]] || continue
@@ -499,6 +511,8 @@ find_mp_fsopts() {
         findmnt -e -v -n -o 'OPTIONS' --target "$1" 2> /dev/null && return 0
     fi
 
+    [[ ! -f "$dracutsysrootdir"/etc/fstab ]] && return 1
+
     findmnt --fstab -e -v -n -o 'OPTIONS' --target "$1"
 }
 
@@ -522,6 +536,8 @@ find_dev_fsopts() {
         findmnt -e -v -n -o 'OPTIONS' --source "$_find_dev" 2> /dev/null && return 0
     fi
 
+    [[ ! -f "$dracutsysrootdir"/etc/fstab ]] && return 1
+
     findmnt --fstab -e -v -n -o 'OPTIONS' --source "$_find_dev"
 }
 
@@ -696,7 +712,7 @@ fs_get_option() {
     while [ $# -gt 0 ]; do
         case $1 in
             $_option=*)
-                echo "${1#${_option}=}"
+                echo "${1#"${_option}"=}"
                 break
                 ;;
         esac
@@ -722,7 +738,7 @@ check_kernel_config() {
 # 0 if the kernel module is either built-in or available
 # 1 if the kernel module is not enabled
 check_kernel_module() {
-    modprobe -S "$kernel" --dry-run "$1" &> /dev/null || return 1
+    modprobe -d "$dracutsysrootdir" -S "$kernel" --dry-run "$1" &> /dev/null || return 1
 }
 
 # get_cpu_vendor
@@ -780,6 +796,14 @@ btrfs_devs() {
         done
 }
 
+zfs_devs() {
+    local _mp="$1"
+    zpool list -H -v -P "${_mp%%/*}" | awk -F$'\t' '$2 ~ /^\// {print $2}' \
+        | while read -r _dev; do
+            realpath "${_dev}"
+        done
+}
+
 iface_for_remote_addr() {
     # shellcheck disable=SC2046
     set -- $(ip -o route get to "$1")
@@ -922,7 +946,7 @@ block_is_nbd() {
 }
 
 # block_is_iscsi <maj:min>
-# Check whether $1 is an nbd device
+# Check whether $1 is an iSCSI device
 block_is_iscsi() {
     local _dir
     local _dev=$1
@@ -959,12 +983,41 @@ block_is_netdevice() {
     block_is_nbd "$1" || block_is_iscsi "$1" || block_is_fcoe "$1"
 }
 
+# convert the driver name given by udevadm to the corresponding kernel module name
+get_module_name() {
+    local dev_driver
+    while read -r dev_driver; do
+        case "$dev_driver" in
+            mmcblk)
+                echo "mmc_block"
+                ;;
+            *)
+                echo "$dev_driver"
+                ;;
+        esac
+    done
+}
+
 # get the corresponding kernel modules of a /sys/class/*/* or/dev/* device
 get_dev_module() {
     local dev_attr_walk
     local dev_drivers
+    local dev_paths
     dev_attr_walk=$(udevadm info -a "$1")
-    dev_drivers=$(echo "$dev_attr_walk" | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p')
+    dev_drivers=$(echo "$dev_attr_walk" \
+        | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p' \
+        | get_module_name)
+
+    # also return modalias info from sysfs paths parsed by udevadm
+    dev_paths=$(echo "$dev_attr_walk" | sed -n 's/.*\(\/devices\/.*\)'\'':/\1/p')
+    local dev_path
+    for dev_path in $dev_paths; do
+        local modalias_file="/sys$dev_path/modalias"
+        if [ -e "$modalias_file" ]; then
+            dev_drivers="$(printf "%s\n%s" "$dev_drivers" "$(cat "$modalias_file")")"
+        fi
+    done
+
     # if no kernel modules found and device is in a virtual subsystem, follow symlinks
     if [[ -z $dev_drivers && $(udevadm info -q path "$1") == "/devices/virtual"* ]]; then
         local dev_vkernel
@@ -981,9 +1034,51 @@ get_dev_module() {
                 [[ -n $dev_drivers && ${dev_drivers: -1} != $'\n' ]] && dev_drivers+=$'\n'
                 dev_drivers+=$(udevadm info -a "$dev_vpath/$dev_link" \
                     | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p' \
+                    | get_module_name \
                     | grep -v -e pcieport)
             done
         fi
     fi
     echo "$dev_drivers"
 }
+
+# Check if file is in PE format
+pe_file_format() {
+    if [[ $# -eq 1 ]]; then
+        local magic
+        magic=$(objdump -p "$1" \
+            | gawk '{if ($1 == "Magic"){print strtonum("0x"$2)}}')
+        magic=$(printf "0x%x" "$magic")
+        # 0x10b (PE32), 0x20b (PE32+)
+        [[ $magic == 0x20b || $magic == 0x10b ]] && return 0
+    fi
+    return 1
+}
+
+# Get specific data from the PE header
+pe_get_header_data() {
+    local data_header
+    [[ $# -ne "2" ]] && return 1
+    [[ $(pe_file_format "$1") -eq 1 ]] && return 1
+    data_header=$(objdump -p "$1" \
+        | awk -v data="$2" '{if ($1 == data){print $2}}')
+    echo "$data_header"
+}
+
+# Get the SectionAlignment data from the PE header
+pe_get_section_align() {
+    local align_hex
+    [[ $# -ne "1" ]] && return 1
+    align_hex=$(pe_get_header_data "$1" "SectionAlignment")
+    [[ $? -eq 1 ]] && return 1
+    echo "$((16#$align_hex))"
+}
+
+# Get the ImageBase data from the PE header
+pe_get_image_base() {
+    local base_image
+    [[ $# -ne "1" ]] && return 1
+    base_image=$(pe_get_header_data "$1" "ImageBase")
+    [[ $? -eq 1 ]] && return 1
+    echo "$((16#$base_image))"
+}