0
  #   lY> T +p-FdN8 ?     #!/bin/bash
#
# weak-modules - determine which modules are kABI compatible with installed
#                kernels and set up the symlinks in /lib/*/weak-updates.
#
unset LANG LC_ALL LC_COLLATE

tmpdir=$(mktemp -td ${0##*/}.XXXXXX)
trap "rm -rf $tmpdir" EXIT
unset ${!changed_modules_*} ${!changed_initramfs_*}

unset BASEDIR
unset CHECK_INITRAMFS
weak_updates_dir_override=""
default_initramfs_prefix="/boot" # will be combined with BASEDIR
dracut="/sbin/dracut"
depmod="/sbin/depmod"
depmod_orig="$depmod"
declare -a modules
declare -A module_krels
declare -A weak_modules_before

declare -A groups
declare -A grouped_modules

# output of validate_weak_links, one iteration
# short_name -> path
declare -A compatible_modules

# state for update_modules_for_krel (needed for add_kernel case)
# short_name -> path
declare -A installed_modules

# doit:
# A wrapper used whenever we're going to perform a real operation.
doit() {
    [ -n "$verbose" ] && echo "$@"
    [ -n "$dry_run" ] || "$@"
}

# pr_verbose:
# print verbose -- wrapper used to print extra messages if required
pr_verbose() {
    [ -n "$verbose" ] && echo "$@"
}

# pr_warning:
# print warning
pr_warning() {
    echo "WARNING: $*"
}

# rpmsort: The sort in coreutils can't sort the RPM list how we want it so we
# instead transform the list into a form it will sort correctly, then sort.
rpmsort() {
    local IFS=$' '
    REVERSE=""
    rpmlist=($(cat))

    if [ "-r" == "$1" ];
    then
        REVERSE="-r"
    fi

    echo ${rpmlist[@]} | \
        sed -e 's/-/../g' | \
        sort ${REVERSE} -n -t"." -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 -k6,6 -k7,7 \
             -k8,8 -k9,9 -k10,10 | \
        sed -e 's/\.\./-/g'
}

# krel_of_module:
# Compute the kernel release of a module.
krel_of_module() {
    local module="$1"

    if [ x"${module_krels[$module]+set}" = x"set" ]; then
        # version cached in the array already
        echo "${module_krels[$module]}"
    elif [ -f "$module" ]; then
        krel_of_module_modinfo "$module"
    else
        # Try to extract the kernel release from the path
        # delete case, the .ko already deleted
        set -- "${module#*/lib/modules/}"
        echo "${1%%/*}"
    fi
}

# krel_of_module_modinfo:
# Fetches module version from internal module info
krel_of_module_modinfo() {
    local module="$1"
    /sbin/modinfo -F vermagic "$module" | awk '{print $1}'
}

# weak_updates_dir:
# gives the root directory for the weak-updates
# We need some flexibility here because of dry-run.
weak_updates_dir() {
    local krel="$1"

    if [[ -z "$weak_updates_dir_override" ]]; then
        echo "$BASEDIR/lib/modules/$krel/weak-updates"
    else
        echo "$weak_updates_dir_override"
    fi
}

# read_modules_list:
# Read in a list of modules from standard input. Convert the filenames into
# absolute paths and compute the kernel release for each module (either using
# the modinfo section or through the absolute path.
# If used with input redirect, should be used as read_module_list < input,
# not input | read_modules_list, the latter spawns a subshell
# and the arrays are not seen in the caller
read_modules_list() {
    local IFS=$'\n'
    modules=($(cat))

    for ((n = 0; n < ${#modules[@]}; n++)); do
        if [ ${modules[n]:0:1} != '/' ]; then
            modules[n]="$PWD/${modules[n]}"
        fi
        module_krels["${modules[n]}"]=$(krel_of_module ${modules[n]})
    done
}

decompress_initramfs() {
    local input=$1
    local output=$2

    # First, check if this is compressed at all
    if cpio -i -t < "$input" > /dev/null 2>/dev/null; then
        # If this archive contains a file early_cpio, it's a trick. Strip off
        # the early cpio archive and try again.
        if cpio -i -t < "$input" 2>/dev/null | grep -q '^early_cpio$' ; then
            /usr/lib/dracut/skipcpio "$input" > "${tmpdir}/post_early_cpio.img"
            decompress_initramfs "${tmpdir}/post_early_cpio.img" "$output"
            retval="$?"
            rm -f "${tmpdir}/post_early_cpio.img"
            return $