• Home (current)
  • वर्तमान निदेशक => /usr/sbin/
  • सूचना एवं अपलोड
    Info Server
Indian Cyber Force
Folders रचयन्तु सञ्चिकां रचयन्तु RansomWeb लॉगआउट
Current File : //usr/sbin/dkms
#!/bin/bash
#
#  Dynamic Kernel Module Support (DKMS) <dkms-devel@dell.com>
#  Copyright (C) 2003-2008 Dell, Inc.
#  by Gary Lerhaupt, Matt Domsch, & Mario Limonciello
#  Copyright (C) 2012 by Darik Horn <dajhorn@vanadac.com>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

shopt -s extglob

# All of the variables we will accept from dkms.conf.
# Does not include directives
readonly dkms_conf_variables="CLEAN REMAKE_INITRD remake_initrd PACKAGE_NAME
   PACKAGE_VERSION POST_ADD POST_BUILD POST_INSTALL POST_REMOVE PRE_BUILD
   PRE_INSTALL BUILD_DEPENDS BUILD_EXCLUSIVE_KERNEL BUILD_EXCLUSIVE_ARCH
   BUILD_EXCLUSIVE_CONFIG
   build_exclude OBSOLETE_BY MAKE MAKE_MATCH MODULES_CONF
   modules_conf_array PATCH PATCH_MATCH patch_array BUILT_MODULE_NAME
   built_module_name BUILT_MODULE_LOCATION built_module_location
   DEST_MODULE_NAME dest_module_name MODULES_CONF_OBSOLETES
   DEST_MODULE_LOCATION dest_module_location
   modules_conf_obsoletes MODULES_CONF_ALIAS_TYPE
   modules_conf_alias_type STRIP strip MODULES_CONF_OBSOLETE_ONLY
   modules_conf_obsolete_only AUTOINSTALL NO_WEAK_MODULES
   SIGN_TOOL"

# Some important regular expressions.  Requires bash 3 or above.
# Any poor souls still running bash 2 or older really need an upgrade.
readonly y_re='^(Y|y)'
readonly mv_re='^([^/]*)/(.*)$'
readonly rh_kernels='(debug|summit|smp|enterprise|bigmem|hugemem|BOOT|vmnix)'

# Areas that will vary between Linux and other OS's
_get_kernel_dir() {
    if [[ -z $ksourcedir_fromcli ]]; then
        KVER=$1
        case ${current_os} in
           Linux)          DIR="/lib/modules/$KVER/build" ;;
           GNU/kFreeBSD)   DIR="/usr/src/kfreebsd-headers-$KVER/sys" ;;
        esac
        echo $DIR
    else
        echo $kernel_source_dir
    fi
}

_check_kernel_dir() {
    DIR=$(_get_kernel_dir $1)
    case ${current_os} in
       Linux)          test -e $DIR/include ;;
       GNU/kFreeBSD)   test -e $DIR/kern && test -e $DIR/conf/kmod.mk ;;
       *)              return 1 ;;
    esac
    return $?
}

# Run a command that we may or may not want to be detailed about.
invoke_command()
{
    # $1 = command to be executed using eval.
    # $2 = Description of command to run
    # $3 = 'background' if you want to run the command asynchronously.
    local exitval=0
    [[ $verbose ]] && echo -e "$1" || echo -en "$2..."
    if [[ $3 = background && ! $verbose ]]; then
        local pid progresspid
        (eval "$1" >/dev/null 2>&1) & pid=$!
        {
            on_exit() {
                kill $(jobs -p) 2>/dev/null
                wait $(jobs -p) 2>/dev/null
            }
            trap on_exit EXIT
            while [ -d /proc/$pid ]; do
                sleep 3 &
                wait $!
                echo -en "."
            done
        } & progresspid=$!
        wait $pid 2>/dev/null
        exitval=$?
        kill $progresspid 2>/dev/null
        wait $progresspid 2>/dev/null
    else
        eval "$1"; exitval=$?
    fi
    (($exitval > 0)) && echo -en "(bad exit status: $exitval)"
    echo -en "\n"
    return $exitval
}

error() (
    exec >&2
    echo -n $"Error! "
    for s in "$@"; do echo "$s"; done
)

warn() (
    exec >&2
    echo -n $"Warning: "
    for s in "$@"; do echo "$s"; done
)

# Print an error message and die with the passed error code.
die() {
    # $1 = error code to return with
    # rest = strings to print before we exit.
    ret=$1
    shift
    error "$@"
    [[ $die_is_fatal = yes ]] && exit $ret || return $ret
}

mktemp_or_die() {
    local t
    t=$(mktemp "$@") && echo "$t" && return
    [[ $* = *-d* ]] && die 1 $"Unable to make temporary directory"
    die 1 "Unable to make temporary file."
}

show_usage()
{
    echo $"Usage: $0 [action] [options]"
    echo $"  [action]  = { add | remove | build | install | uninstall | match | autoinstall | mkdriverdisk |"
    echo $"                mktarball | ldtarball | mkrpm | mkkmp | mkdeb | mkdsc | mkbmdeb | status }"
    echo $"  [options] = [-m module] [-v module-version] [-k kernel-version] [-a arch]"
    echo $"              [-d distro] [-c dkms.conf-location] [-q] [--force] [--force-version-override] [--all]"
    echo $"              [--templatekernel=kernel] [--directive='cli-directive=cli-value']"
    echo $"              [--config=kernel-.config-location] [--archive=tarball-location]"
    echo $"              [--kernelsourcedir=source-location] [--no-prepare-kernel] [--no-initrd]"
    echo $"              [--binaries-only] [--source-only] [-r release (SuSE)] [--verbose]"
    echo $"              [--size] [--spec=specfile] [--media=floppy|iso|tar] [--legacy-postinst=0|1]"
    echo $"              [--no-depmod] [-j number] [--version]"
}

VER()
{
    # $1 = kernel version string

    # Pad all numbers in $1 so that they have at least three digits, e.g.,
    #   2.6.9-1cvs200409091247 => 002.006.009-001cvs200409091247
    # The result should compare correctly as a string.

    echo $1 | sed -e 's:\([^0-9]\)\([0-9]\):\1 \2:g' \
        -e 's:\([0-9]\)\([^0-9]\):\1 \2:g' \
        -e 's:\(.*\): \1 :' \
        -e 's: \([0-9]\) : 00\1 :g' \
        -e 's: \([0-9][0-9]\) : 0\1 :g' \
        -e 's: ::g'
}

# Find out how many CPUs there are so that we may pass an appropriate -j
# option to make. Ignore hyperthreading for now.
get_num_cpus()
{
   # use nproc(1) from coreutils 8.1-1+ if available, otherwise single job
   if [ -x /usr/bin/nproc ]; then
	nproc
   else
	echo "1"
  fi
}

# Finds a .ko or .ko.xz based on a directory and module name
# must call set_module_suffix first
compressed_or_uncompressed()
{
    # module dir = $1
    # module = $2
    local test1="$1/$2$module_uncompressed_suffix"
    local test2="$1/$2$module_uncompressed_suffix$module_compressed_suffix"
    if [[ -e "$test1" ]]; then
        echo "$test1"
    elif [[ -e "$test2" ]]; then
        echo "$test2"
    fi
}

# Finds .ko or .ko.xz based on a tree and module name
# must call set_module_suffix first
find_module()
{
    # tree = $1
    # module = $2
    find "$1" -name "$2$module_uncompressed_suffix" -o -name "$2$module_suffix" -type f
    return $?
}


# Figure out the correct module suffix for the kernel we are currently
# dealing with, which may or may not be the currently installed kernel.
set_module_suffix()
{
    # $1 = the kernel to base the module_suffix on
    kernel_test="${1:-$(uname -r)}"
    module_uncompressed_suffix=".ko"
    [[ $(VER $kernel_test) < $(VER 2.5) ]] && module_uncompressed_suffix=".o"
    grep -q '\.gz:' /lib/modules/$kernel_test/modules.dep 2>/dev/null && module_compressed_suffix=".gz"
    grep -q '\.xz:' /lib/modules/$kernel_test/modules.dep 2>/dev/null && module_compressed_suffix=".xz"
    grep -q '\.zst:' /lib/modules/$kernel_test/modules.dep 2>/dev/null && module_compressed_suffix=".zst"
    module_suffix="$module_uncompressed_suffix$module_compressed_suffix"
}

set_kernel_source_dir()
{
    if [[ -z $ksourcedir_fromcli ]]; then
        # $1 = the kernel to base the directory on
        kernel_source_dir="$(_get_kernel_dir "$1")"
    fi
}

check_all_is_banned()
{
    if [[ $all ]]; then
        die 5 $"The action $1 does not support the --all parameter."
    fi
}

# A little test function for DKMS commands that only work on one kernel.
have_one_kernel() {
    if (( ${#kernelver[@]} != 1 )); then
        die 4 $"The action $1 does not support multiple kernel version parameters on the command line."
    fi
    check_all_is_banned $1
}

# Set up the kernelver and arch arrays.  You must have a 1:1 correspondence --
# if there is an entry in kernelver[$i], there must also be an entry in arch[$i]
# Note the special casing for the status action -- the status functions just
# report on what we already have, and will break with the preprocessing that
# this function provides.
setup_kernels_arches()
{
    # If all is set, use dkms status to fill the arrays
    if [[ $all && $1 != status ]]; then
        local i=0
        while read line; do
            line=${line#*/}; line=${line#*/};
            # (I would leave out the delimiters in the status output
            #  in the first place.)
            kernelver[$i]=${line%/*}
            arch[$i]=${line#*/}
            i=$(($i + 1))
        done < <(module_status_built "$module" "$module_version")
    fi

    # Set default kernel version and arch, if none set (but only --all isn't set)
    if [[ $1 != status ]]; then
        if [[ ! $kernelver && ! $all ]]; then
            kernelver[0]=$(uname -r)
        fi
        if [[ ! $arch ]]; then
            kernelver_rpm=$(rpm -qf "/lib/modules/$kernelver" 2>/dev/null | \
            grep -v "not owned by any package" | grep kernel | head -n 1)
            if ! arch[0]=$(rpm -q --queryformat "%{ARCH}" "$kernelver_rpm" 2>/dev/null); then
                arch[0]=$(uname -m)
                if [[ $arch = x86_64 ]] && grep -q Intel /proc/cpuinfo && ls $install_tree/$kernelver/build/configs 2>/dev/null | grep -q "ia32e"; then
                    arch[0]="ia32e"
                fi
            fi
        fi
    fi

    # If only one arch is specified, make it so for all the kernels
    if ((${#arch[@]} == 1 && ${#kernelver[@]} > 1)); then
        while ((${#arch[@]} < ${#kernelver[@]})); do
            arch[${#arch[@]}]=$arch
        done
    fi

    # Set global multi_arch
    multi_arch=""
    local i=0
    for ((i=0; $i < ${#arch[@]}; i++)); do
        [[ $arch != ${arch[$i]} ]] && {
            multi_arch="true"
            break
        }
    done
}

do_depmod()
{
    if [[ $no_depmod ]]; then
        return
    fi
    # $1 = kernel version
    if [ "${current_os}" != "Linux" ] ; then
        return
    fi
    if [[ -f /boot/System.map-$1 ]]; then
        depmod -a "$1" -F "/boot/System.map-$1"
    else
        depmod -a "$1"
    fi
}

# This function is a little hairy -- every distro has slightly different tools
# and naming conventions for creating initial ramdisks.  It should probably
# be split out into one function per distro, with make_initrd left as a stub.
make_initrd()
{
    # $1 = kernel version
    # $2 = arch
    # $3 = 'backup', if backup of old initrd is wanted (using .old-dkms filename suffix)

    [[ $no_initrd ]] && return
    local mkinitrd kernel_file initrd_dir="/boot"
    for mkinitrd in dracut update-initramfs mkinitrd ''; do
        [[ $mkinitrd ]] && which "$mkinitrd" >/dev/null 2>&1 && break
    done

    # No mkinitrd? Just return.
    [[ $mkinitrd ]] || return 0

    # Back up our current initrd
    echo $""
    # Find out what the proper filename will be
    for initrd in "initrd-$1.img" "initramfs-$1.img" "initrd.img-$1" "initrd-$1" ''; do
        [[ $initrd && -f $initrd_dir/$initrd ]] && break
    done
    if ! [[ $initrd ]]; then
        # Return if we cannot find an initrd.
        warn $"Unable to find an initial ram disk that I know how to handle." \
            $"Will not try to make an initrd."
        return 0
    fi
    if [[ $3 = backup ]]; then
        echo $"Backing up $initrd to $initrd_dir/$initrd.old-dkms"
        cp -f "$initrd_dir/$initrd" "$initrd_dir/$initrd.old-dkms"
        echo $"Making new $initrd"
        echo $"(If next boot fails, revert to $initrd.old-dkms image)"
    fi

    if [[ $mkinitrd = dracut ]]; then
        invoke_command "$mkinitrd -f $initrd_dir/$initrd $1" "$mkinitrd" background
    elif [[ $mkinitrd = update-initramfs ]]; then
        invoke_command "$mkinitrd -u -k $1" "$mkinitrd" background
    elif $mkinitrd --version >/dev/null 2>&1; then
        invoke_command "$mkinitrd -f $initrd_dir/$initrd $1" "$mkinitrd" background
    elif [[ -e /etc/SuSE-release || -d /etc/SuSEconfig ]]; then
        for kernel_file in vmlinuz vmlinux ''; do
            [[ $kernel_file && -f $initrd_dir/$kernel_file ]] && break
        done
        if [[ ! $kernel_file ]]; then
            error $"Unable to find valid kernel file under " \
            $"$initrd_dir for kernel version $1"
            return 1;
        fi
        invoke_command "$mkinitrd -k $kernel_file-$1 -i $initrd" "$mkinitrd" background
    elif [[ -e /etc/debian_version ]]; then
        invoke_command "$mkinitrd -o $initrd_dir/$initrd $1" "$mkinitrd" background
    else
        echo $""
        echo $"Calling $mkinitrd (bad exit status 9 may occur)"
        invoke_command "$mkinitrd" "$mkinitrd" background
    fi
    return
}

# Grab our distro information from RPM-based distros.
distro_version_rpm()
{
    which rpm > /dev/null 2>&1 || { echo unknown; return; }
    local r wp ver dist

    for r in redhat-release sles-release suse-release ovs-release; do
        wp=$(rpm -q --whatprovides "$r") || continue
        ver=$(rpm -q --qf "%{version}\n" ${wp})
        case $r in
            sles*)
                echo sles${ver}
                ;;
            suse*)
                echo suse${ver}
                ;;
            ovs*)
                echo ovm${ver}
                ;;
            redhat*)
                case $wp in
                    redhat*|sl*)
                        ver=$(echo $ver | \
                        sed -e 's/^\([[:digit:]]*\).*/\1/g')
                        echo el${ver}
                        ;;
                    centos*|enterprise*)
                        echo el${ver}
                        ;;
                    fedora*)
                        echo fc${ver}
                        ;;
                    *)
                        echo unknown
                        ;;
                esac
                ;;
            *)
                echo unknown
                ;;
        esac
        return
    done
    echo unknown
}

# Grab distro information from LSB compliant distros.
# Falls back to distro_version_rpm if needed.
distro_version()
{
    # What distribution are we running?
    local LSB_DESCRIPTION DISTRIB_ID DISTRIB_RELEASE ver

    # Try the LSB-provided strings first
    if [ -r /etc/lsb-release ]; then
        . /etc/lsb-release
    elif type lsb_release >/dev/null 2>&1; then
        DISTRIB_ID=$(lsb_release -i -s)
        DISTRIB_RELEASE=$(lsb_release -r -s)
    fi

    case ${DISTRIB_ID} in
        Fedora)
            echo fc${DISTRIB_RELEASE}
            ;;
        RedHatEnterprise*|CentOS|ScientificSL)
            # OEL also reports as such; format is 4.7, 5.3
            ver=$(echo "${DISTRIB_RELEASE}" | \
            sed -e 's/^\([[:digit:]]*\).*/\1/g')
            echo el${ver}
            ;;
        SUSE*)
            if [[ $(lsb_release -d -s) =~ Enterprise ]]; then
                echo sles${DISTRIB_RELEASE}
            else
                echo suse${DISTRIB_RELEASE}
            fi
            ;;
        *)
            if [[ ${DISTRIB_ID} && ${DISTRIB_RELEASE} ]]; then
                echo "${DISTRIB_ID}${DISTRIB_RELEASE}"
            else
                distro_version_rpm
            fi
            ;;
    esac
}

override_dest_module_location()
{
    local orig_location="$1"
    [[ ${addon_modules_dir} ]] && echo "/${addon_modules_dir}" && return

    if [ "$current_os" = "GNU/kFreeBSD" ] ; then
        # Does not support subdirs, regardless of distribution
        echo "" && return
    fi

    case "$running_distribution" in
    sles[123456789])
        ;;
    suse[123456789])
        ;;
    suse10\.[01])
        ;;
    fc*)
        echo "/extra" && return
        ;;
    el*)
        echo "/extra" && return
        ;;
    ovm*)
        echo "/extra" && return
        ;;
    sles*)
        echo "/updates" && return
        ;;
    suse*)
        echo "/updates" && return
        ;;
    Ubuntu*)
        echo "/updates/dkms" && return
        ;;
    Debian*)
        echo "/updates/dkms" && return
        ;;
    *)
        ;;
    esac
    echo "$orig_location"
}

# Source a file safely.
# We want to ensure that the .conf file we source does not stomp all over
# parts of the environment we don't want them to.  This makes it so that
# it is harder to accidentally corrupt our environment.  conf files can
# still deliberately trash the environment by abusing dkms_directive env
# variables or by crafting special values that will make eval do evil things.
safe_source() {
    # $1 = file to source
    # $@ = environment variables to echo out
    local to_source_file="$1"; shift
    declare -a -r export_envs=("$@")
    local tmpfile=$(mktemp_or_die)
    ( exec >"$tmpfile"
    . "$to_source_file" >/dev/null
    # This is really ugly, but a neat hack
    # Remember, in bash 2.0 and greater all variables are really arrays.
    for _export_env in "${export_envs[@]}"; do
        for _i in $(eval echo \${!$_export_env[@]}); do
            eval echo '$_export_env[$_i]=\"${'$_export_env'[$_i]}\"'
        done
    done

    # handle DKMS_DIRECTIVE stuff specially.
    for directive in $(set | grep ^DKMS_DIRECTIVE | cut -d = -f 2-3); do
        directive_name=${directive%%=*}
        directive_value=${directive#*=}
        echo "$directive_name=\"$directive_value\""
    done
    )
    . "$tmpfile"
    rm "$tmpfile"
}

# Source a dkms.conf file and perform appropriate postprocessing on it.
# Do our best to not repeatedly source the same .conf file -- this can happen
# when chaining module installation functions or autoinstalling.
read_conf()
{
    # $1 kernel version (required)
    # $2 arch (required)
    # $3 dkms.conf location (optional)

    local return_value=0
    local read_conf_file="$dkms_tree/$module/$module_version/source/dkms.conf"

    # Set variables supported in dkms.conf files (eg. $kernelver)
    local kernelver="$1"
    local arch="$2"
    set_kernel_source_dir "$1"


    # Find which conf file to check
    [[ $conf ]] && read_conf_file="$conf"
    [[ $3 ]] && read_conf_file="$3"

    [[ -r $read_conf_file ]] || die 4 $"Could not locate dkms.conf file." \
    $"File: $read_conf_file does not exist."

    [[ $last_mvka = $module/$module_version/$1/$2 && \
    $last_mvka_conf = $(readlink -f $read_conf_file) ]] && return


    # Clear variables and arrays
    for var in $dkms_conf_variables; do
        unset $var
    done

    # Source in the dkms.conf.
    # Allow for user-specified overrides in order of specificity.
    local _conf_file
    for _conf_file in "$read_conf_file" "/etc/dkms/$module.conf" \
        "/etc/dkms/$module-$module_version.conf" "/etc/dkms/$module-$module_version-$1.conf" \
        "/etc/dkms/$module-$module_version-$1-$2.conf"; do
        [ -e "$_conf_file" ] && safe_source "$_conf_file" $dkms_conf_variables
    done

    # Source in the directive_array
    for directive in "${directive_array[@]}"; do
        directive_name=${directive%%=*}
        directive_value=${directive#*=}
        export $directive_name="$directive_value"
        echo $"DIRECTIVE: $directive_name=\"$directive_value\""
    done

    # Set variables
    clean="$CLEAN"
    package_name="$PACKAGE_NAME"
    package_version="$PACKAGE_VERSION"
    post_add="$POST_ADD"
    post_build="$POST_BUILD"
    post_install="$POST_INSTALL"
    post_remove="$POST_REMOVE"
    pre_build="$PRE_BUILD"
    pre_install="$PRE_INSTALL"
    obsolete_by="$OBSOLETE_BY"

    # Set module naming/location arrays
    local index array_size=0 s
    for s in ${#BUILT_MODULE_NAME[@]} \
        ${#BUILT_MODULE_LOCATION[@]} \
        ${#DEST_MODULE_NAME[@]} \
        ${#DEST_MODULE_LOCATION[@]}; do
        ((s > array_size)) && array_size=$s
    done
    for ((index=0; index < array_size; index++)); do
        # Set values
        built_module_name[$index]=${BUILT_MODULE_NAME[$index]}
        built_module_location[$index]=${BUILT_MODULE_LOCATION[$index]}
        dest_module_name[$index]=${DEST_MODULE_NAME[$index]}
        dest_module_location[$index]=${DEST_MODULE_LOCATION[$index]}
        modules_conf_obsoletes[$index]=${MODULES_CONF_OBSOLETES[$index]}
        modules_conf_alias_type[$index]=${MODULES_CONF_ALIAS_TYPE[$index]}
        case ${MODULES_CONF_OBSOLETE_ONLY[$index]} in
            [yY]*)
                modules_conf_obsolete_only[$index]="yes"
                ;;
        esac
        case ${STRIP[$index]} in
            [nN]*)
                strip[$index]="no"
                ;;
            [yY]*)
                strip[$index]="yes"
                ;;
            '')
                strip[$index]=${strip[0]:-yes}
                ;;
        esac

        # If unset, set by defaults
        [[ ! ${built_module_name[$index]} ]] && \
            ((${#DEST_MODULE_LOCATION[@]} == 1)) && \
            built_module_name[$index]=$module
        [[ ! ${dest_module_name[$index]} ]] && \
            dest_module_name[$index]=${built_module_name[$index]}
        [[ ${built_module_location[$index]} && \
            ${built_module_location[$index]:(-1)} != / ]] && \
            built_module_location[$index]="${built_module_location[$index]}/"

        # FAIL if no built_module_name
        if [[ ! ${built_module_name[$index]} ]]; then
            echo $"dkms.conf: Error! No 'BUILT_MODULE_NAME' directive specified for record #$index." >&2
            return_value=1
        fi

        # FAIL if built_module_name ends in .o or .ko
        case ${built_module_name[$index]} in
            *.o|*.ko)
                echo $"dkms.conf: Error! 'BUILT_MODULE_NAME' directive ends in '.o' or '.ko' in record #$index." >&2
                return_value=1
                ;;
        esac

        # FAIL if dest_module_name ends in .o or .ko
        case ${dest_module_name[$index]} in
            *.o|*.ko)
                echo $"dkms.conf: Error! 'DEST_MODULE_NAME' directive ends in '.o' or '.ko' in record #$index." >&2
                return_value=1
                ;;
        esac

        # Override location for specific kernels
        dest_module_location[$index]="$(override_dest_module_location ${dest_module_location[$index]})"

        # Fail if no DEST_MODULE_LOCATION
        if [[ ! ${DEST_MODULE_LOCATION[$index]} ]]; then
            echo $"dkms.conf: Error! No 'DEST_MODULE_LOCATION' directive specified for record #$index.">&2
            return_value=1
        fi
            # Fail if bad DEST_MODULE_LOCATION
        case ${DEST_MODULE_LOCATION[$index]} in
            /kernel*)
                ;;
            /updates*)
                ;;
            /extra*)
                ;;
            *)
            echo $"dkms.conf: Error! Directive 'DEST_MODULE_LOCATION' does not begin with">&2
            echo $"'/kernel', '/updates', or '/extra' in record #$index.">&2
            return_value=1
            ;;
        esac
    done

    # Get the correct make command
    [[ ${MAKE_MATCH[0]} ]] || make_command="${MAKE[0]}"
    for ((index=0; index < ${#MAKE[@]}; index++)); do
    [[ ${MAKE[$index]} && ${MAKE_MATCH[$index]} && \
        $1 =~ ${MAKE_MATCH[$index]} ]] && \
        make_command="${MAKE[$index]}"
    done

    # Use the generic make and make clean commands if not specified
    if [[ $(VER $1) < $(VER 2.6.6) ]]; then
        [[ ! $make_command ]] && make_command="make -C $kernel_source_dir SUBDIRS=$dkms_tree/$module/$module_version/build modules"
        [[ ! $clean ]] && clean="make -C $kernel_source_dir SUBDIRS=$dkms_tree/$module/$module_version/build clean"
    else
        [[ ! $make_command ]] && make_command="make -C $kernel_source_dir M=$dkms_tree/$module/$module_version/build"
        [[ ! $clean ]] && clean="make -C $kernel_source_dir M=$dkms_tree/$module/$module_version/build clean"
    fi

    # Set modules_conf_array
    for ((index=0; index < ${#MODULES_CONF[@]}; index++)); do
        [[ ${MODULES_CONF[$index]} ]] && modules_conf_array[$index]="${MODULES_CONF[$index]}"
    done

    # Set patch_array (including kernel specific patches)
    count=0
    for ((index=0; index < ${#PATCH[@]}; index++)); do
    if [[ ${PATCH[$index]} && (! ${PATCH_MATCH[$index]} || $1 =~ ${PATCH_MATCH[$index]}) ]]; then
        patch_array[$count]="${PATCH[$index]}"
        count=$(($count+1))
    fi
    done

    # Set remake_initrd
    [[ $REMAKE_INITRD =~ $y_re ]] && remake_initrd="yes"

    # Set build_exclude
    [[ $BUILD_EXCLUSIVE_KERNEL && ! $1 =~ $BUILD_EXCLUSIVE_KERNEL ]] && build_exclude="yes"
    [[ $BUILD_EXCLUSIVE_ARCH && ! $2 =~ $BUILD_EXCLUSIVE_ARCH ]] && build_exclude="yes"
    if [[ $BUILD_EXCLUSIVE_CONFIG && -e $kernel_source_dir/.config ]]; then
	local kconf
        for kconf in $BUILD_EXCLUSIVE_CONFIG ; do
            case "$kconf" in
                !*) grep -q -E "^${kconf#!}=[ym]" $kernel_source_dir/.config && build_exclude="yes" ;;
                *)  grep -q -E "^${kconf}=[ym]" $kernel_source_dir/.config || build_exclude="yes" ;;
            esac
        done
    fi

    # Fail if absolutely no DEST_MODULE_LOCATION
    if ((${#dest_module_location[@]} == 0)); then
        echo $"dkms.conf: Error! No 'DEST_MODULE_LOCATION' directive specified." >&2
        return_value=1
    fi

    # Fail if no PACKAGE_NAME
    if [[ ! $package_name ]]; then
        echo $"dkms.conf: Error! No 'PACKAGE_NAME' directive specified.">&2
        return_value=1
    fi

    # Fail if no PACKAGE_VERSION
    if [[ ! $package_version ]]; then
        echo $"dkms.conf: Error! No 'PACKAGE_VERSION' directive specified.">&2
        return_value=1
    fi

    # Set clean
    [[ $clean ]] || clean="make clean"

    ((return_value == 0)) && last_mvka="$module/$module_version/$1/$2" && last_mvka_conf="$(readlink -f "$read_conf_file")"
    return $return_value
}

# Little helper function for parsing the output of modinfo.
get_module_verinfo(){
    res=("" "" "")
    local vals=
    while read -a vals; do
    case ${vals[0]} in
        version:)
            res[0]=${vals[1]}
            res[2]=${vals[2]}
            ;;
        srcversion:)
        res[1]=${vals[1]}
        ;;
    esac
    done < <(modinfo $1)
}

# Perform some module version sanity checking whenever we are installing
# or removing modules.
check_version_sanity()
{
    # $1 = kernel_version
    # $2 = arch
    # $3 = obs by kernel version
    # $4 = dest_module_name

    local lib_tree="$install_tree/$1" res=
    echo $"Running module version sanity check."
    local i=0
    local -a kernels_info dkms_info
    if [ -n $3 ]; then
        # Magic split into array syntax saves trivial awk and cut calls.
        local -a obs=(${3//-/ })
        local -a my=(${1//-/ })
        local obsolete=0
        if [[ ${obs} && ${my} ]]; then
            if [[ $(VER ${obs}) == $(VER ${my}) && ! $force ]]; then
                # They get obsoleted possibly in this kernel release
                if [[ ! ${obs[1]} ]]; then
                    # They were obsoleted in this upstream kernel
                    obsolete=1
                elif [[ $(VER ${my[1]}) > $(VER ${obs[1]}) ]]; then
                    # They were obsoleted in an earlier ABI bump of the kernel
                    obsolete=1
                elif [[ $(VER ${my[1]}) = $(VER ${obs[1]}) ]]; then
                    # They were obsoleted in this ABI bump of the kernel
                    obsolete=1
                fi
            elif [[ $(VER ${my}) > $(VER ${obs}) && ! $force ]]; then
                # They were obsoleted in an earlier kernel release
                obsolete=1
            fi
        fi

        if ((obsolete == 1)); then
            echo $"" >&2
            echo $"Module has been obsoleted due to being included" >&2
            echo $"in kernel $3.  We will avoid installing" >&2
            echo $"for future kernels above $3." >&2
            echo $"You may override by specifying --force." >&2
            return 1
        fi
    fi
    set_module_suffix "$1"
    read -a kernels_module < <(find_module "$lib_tree" "${4}")
    [ -z $kernels_module ] && return 0

    if [[ "$force_version_override" == "true" ]]; then
        # Skip the following version checking code.
        return 0
    fi

    if [[ ${kernels_module[1]} ]]; then
        warn $"Warning! Cannot do version sanity checking because multiple ${4}$module_suffix" \
            $"modules were found in kernel $1."
        return 0
    fi
    local dkms_module=$(compressed_or_uncompressed "$dkms_tree/$module/$module_version/$1/$2/module/" "${4}")
    get_module_verinfo $kernels_module; kernels_info=("${res[@]}")
    get_module_verinfo $dkms_module; dkms_info=("${res[@]}")
    if [[ ! ${dkms_info[1]} && ${kernels_info[1]} ]]; then
        # Use obsolete checksum info
        dkms_info[1]=${dkms_info[2]}
        kernels_info[1]=${kernels_info[2]}
    fi

    if [[ ${kernels_info[1]} && ${dkms_info[1]} && ${kernels_info[1]} = ${dkms_info[1]} &&
	  -n "${kernels_info[0]}" && -n "${dkms_info[0]}" && ${kernels_info[0]} = ${dkms_info[0]} && ! $force ]]; then
        echo $"" >&2
        echo $"Good news! Module version $dkms_info for ${4}$module_suffix" >&2
        echo $"exactly matches what is already found in kernel $1." >&2
        echo $"DKMS will not replace this module." >&2
        echo $"You may override by specifying --force." >&2
        return 1
    fi

    if [[ $kernels_info && $dkms_info && ! ( $(VER $dkms_info) > $(VER $kernels_info) ) && ! $force ]]; then
        error $"Module version $dkms_info for ${4}$module_suffix" \
            $"is not newer than what is already found in kernel $1 ($kernels_info)." \
            $"You may override by specifying --force."
        return 1
    fi

    return 0
}

moduleconfig_update_obsoletes()
{
    # $@ = files to process
    # Do nothing if we have no obsoletes
    ( IFS=; [[ "${modules_conf_obsoletes[*]}" ]] ) || return 0
    # Generate sed args to remove obsolete modules
    local mod_diff
    for ((index=0; index < ${#dest_module_name[@]}; index++)); do
        [[ ${modules_conf_obsoletes[$index]} ]] || continue
        for obsolete_module in ${modules_conf_obsoletes[$index]//,/ }; do
            # For module.conf style syntax
            sa_mc_o[${#sa_mc_o[*]}]="-e"
            sa_mc_o[${#sa_mc_o[*]}]="s/\(alias ${modules_conf_alias_type[$index]}[0-9]*\) $obsolete_module$/\1 ${dest_module_name[$index]}/g"
            # For /etc/sysconfig/kernel style syntax
            sa_sck_o[${#sa_sck_o[*]}]="-e"
            sa_sck_o[${#sa_sck_o[*]}]="s/\(INITRD_MODULES.*\)$obsolete_module\b\(.*\)/\1${dest_module_name[$index]}\2/"
        done
    done

    # Do all the changes at once, record the diffs for posterity
    for file in "$@"; do
        [[ $file && -w $file ]] || continue
        _tmpf="$temp_dir_name/${file##*/}.new"
        if [[ $file = /etc/sysconfig/kernel ]]; then
            [ -z "${sa_sck_o[@]}" ] || sed "${sa_sck_o[@]}" "$file" > "$_tmpf"
        else
            [ -z "${sa_mc_o[@]}" ] || sed "${sa_mc_o[@]}" "$file" > "$_tmpf"
        fi
	if [ -f "$_tmpf" ] && ! mod_diff=$(diff -u "$_tmpf" "$file"); then
            echo $"$file updated to replace obsoleted module references:"
            echo "$mod_diff"
            cp -fp "$_tmpf" "$file"
            rm -f "$_tmpf"
        fi
    done
}

moduleconfig_add()
{
    # $1 = kernel version

    local temp_dir_name=$(mktemp_or_die -d $tmp_location/dkms.XXXXXX)
    local -a sa_mc_o=() sa_sck_o=()
    modconfig_files="/etc/modprobe.d/dkms.conf
        /etc/modprobe.d/dkms
        /etc/modules.conf
        /etc/modprobe.conf
        /etc/modprobe.d/$package_name.conf
        /etc/sysconfig/kernel"

    moduleconfig_update_obsoletes $modconfig_files

    for moduleconfig in $modconfig_files; do
    [[ -e $moduleconfig ]] || continue
    for ((index=0; index < ${#dest_module_name[@]}; index++)); do

        # Only add it if it can't be found already in config file
        if [[ ${modules_conf_alias_type[$index]} ]] && \
           ! grep -qs "alias ${modules_conf_alias_type[$index]}[0-9]* ${dest_module_name[$index]}\b" $moduleconfig && \
           [[ ${modules_conf_obsolete_only[$index]} != yes ]]; then
            if [[ $modconfig_files = /etc/modprobe.d/$package_name.conf ]] && [[ ! -e /etc/modprobe.d/$package_name.conf ]]; then
                touch /etc/modprobe.d/$package_name.conf
                echo $"created /etc/modprobe.d/$package_name.conf.">&2
            fi
            aliases=$(awk "/^alias ${modules_conf_alias_type[$index]}/ {print \$2}" $moduleconfig)
            if [[ $aliases ]]; then
                alias_number=$(($(echo "$aliases" | sed "s/${modules_conf_alias_type[$index]}//" | sort -n | tail -n 1) + 1))
            else
                alias_number=0
            fi
            echo -e "alias ${modules_conf_alias_type[$index]}${alias_number} ${dest_module_name[$index]}" >> $moduleconfig
            echo $"$moduleconfig: added alias reference for '${dest_module_name[$index]}'"
        fi
    done

    # Add anything else
    for ((index=0; index < ${#modules_conf_array[@]}; index++)); do
        if [ -n "${modules_conf_array[$index]}" ] && \
        ! grep -q "${modules_conf_array[$index]}" "$moduleconfig"; then
        echo -e $"$moduleconfig: added '${modules_conf_array[$index]}'"
        echo -e "${modules_conf_array[$index]}" >> $moduleconfig
        fi
    done
    done

    # Delete the temp dir
    rm -rf $temp_dir_name
}

moduleconfig_remove()
{
    # $1 = kernel version

    local temp_dir_name=$(mktemp_or_die -d $tmp_location/dkms.XXXXXX)
    modconfig_files=""
    [ -e /etc/modprobe.d/dkms.conf ] && modconfig_files="/etc/modprobe.d/dkms.conf"
    [ -e /etc/modprobe.d/dkms ] && modconfig_files="/etc/modprobe.d/dkms"
    [ -e /etc/modules.conf ] && modconfig_files="$modconfig_files /etc/modules.conf"
    [ -e /etc/modprobe.conf ] && modconfig_files="$modconfig_files /etc/modprobe.conf"
    [ -e /etc/modprobe.d/$package_name.conf ] && modconfig_files="/etc/modprobe.d/$package_name.conf"

    for moduleconfig in $modconfig_files; do
        for ((index=0; index < ${#dest_module_name[@]}; index++)); do
            # Remove/Replace aliases (maybe)
            [[ ${modules_conf_alias_type[$index]} ]] || continue
            find "$install_tree/$1/" -name "${dest_module_name[$index]}.*" -quit 2>/dev/null && continue

            local conf_replacement=""
            for obsolete_module in ${modules_conf_obsoletes[$index]//,/ }; do
                find $install_tree/$1/ -name "$obsolete_module.*" -quit 2>/dev/null || continue
                conf_replacement=$obsolete_module
                break
            done

            if [[ ! $conf_replacement ]]; then
                grep -v "alias ${modules_conf_alias_type[$index]}[0-9]* ${dest_module_name[$index]}" $moduleconfig > $temp_dir_name/moduleconfig.new
                mv -f $temp_dir_name/moduleconfig.new $moduleconfig
                echo $"$moduleconfig: removed alias for '${dest_module_name[$index]}'"
                if [[ $modconfig_files = /etc/modprobe.d/$package_name.conf ]]; then
                    rm -f /etc/modprobe.d/$package_name.conf
                    echo $"$moduleconfig: deleted /etc/modprobe.d/$package_name.conf file"
                fi
                elif grep -q "alias ${modules_conf_alias_type[$index]}[0-9]* ${dest_module_name[$index]}$" $moduleconfig; then
                    sed "s/\(alias ${modules_conf_alias_type[$index]}[0-9]*\) ${dest_module_name[$index]}$/\1 $conf_replacement/g" \
                        $moduleconfig > $temp_dir_name/moduleconfig.new
                    mv -f $temp_dir_name/moduleconfig.new $moduleconfig
                    echo $"$moduleconfig: alias for '${dest_module_name[$index]}' changed back to '$conf_replacement'"
            fi
        done

        # Remove static conf entries
        for ((index=0; index < ${#modules_conf_array[@]}; index++)); do
            [[ ${modules_conf_array[$index]} ]] || continue
            grep -v "${modules_conf_array[$index]}" "$moduleconfig" > $temp_dir_name/moduleconfig.new
            echo $"$moduleconfig: removed '${modules_conf_array[$index]}'"
            mv -f $temp_dir_name/moduleconfig.new $moduleconfig
        done
    done

    # Delete the temp dir
    rm -rf $temp_dir_name
}

etc_sysconfig_kernel_modify()
(
    [[ -f /etc/sysconfig/kernel && $remake_initrd ]] || return 0

    # Make a temp directory to store files
    local temp_dir_name=$(mktemp_or_die -d $tmp_location/dkms.XXXXXX)
    if [[ $1 = add ]]; then
        . /etc/sysconfig/kernel
        for m in "${dest_module_name[@]}"; do
            for l in "${INITRD_MODULES}"; do
                [[ $m = $l ]] && continue 2
            done
            sed -e "s/INITRD_MODULES=\"\(.*\)\"/INITRD_MODULES=\"\1 $m\"/" /etc/sysconfig/kernel > $temp_dir_name/kernel.new
            mv $temp_dir_name/kernel.new /etc/sysconfig/kernel
        done
    # Remove /etc/sysconfig/kernel entries
    elif [[ $1 = delete ]]; then
        for m in "${dest_module_name[@]}"; do
            sed -e "s/\(INITRD_MODULES.*\)$m\b\(.*\)/\1\2/" /etc/sysconfig/kernel > $temp_dir_name/kernel.new
            mv $temp_dir_name/kernel.new /etc/sysconfig/kernel
        done
    fi
    # Delete the temp dir
    rm -rf $temp_dir_name
)

check_module_args() {
    [[ $module && $module_version ]] && return
    die 1 $"Arguments <module> and <module-version> are not specified." \
        $"Usage: $1 <module>/<module-version> or" \
        $"       $1 -m <module>/<module-version> or" \
        $"       $1 -m <module> -v <module-version>"
}

read_conf_or_die() {
    read_conf "$@" && return
    die 8 $"Bad conf file."\
        $"File: $conf does not represent a valid dkms.conf file."
}

run_build_script() {
    # $1 = script type
    # $2 = script to run
    local script_type run
    [[ $2 ]] || return 0
    case "$1" in
        pre_build|post_build)
            script_type='build'
            ;;
        *)
            script_type='source'
            ;;
    esac
    run="$dkms_tree/$module/$module_version/$script_type/$2"
    if [[ -x ${run%% *} ]]; then
        echo $""
        echo $"Running the $1 script:"
        (
            cd "$dkms_tree/$module/$module_version/$script_type/"
            exec $run
        )
    else
        echo $""
        warn $"The $1 script is not executable."
    fi
}

run_sign_tool() {
    # $1 = sign tool to run
    # $2 = module file to sign
    local logfile="$base_dir/log/make.log"
    if [[ -x "$1" ]]; then
        echo "Signing $2" >> "$logfile"
        "$1" "$kernelver" "$2" || \
        report_build_problem 11 $"Bad exit status $? for sign tool." \
            $"Consult $logfile for more information."
    else
        echo $""
        warn $"The $1 is not executable."
    fi
}

# Register a DKMS-ified source tree with DKMS.
# This function is smart enough to register the module if we
# passed a source tree or a tarball instead of relying on the source tree
# being unpacked into /usr/src/$module-$module_version.
add_module()
{
    # If $archive is set and $module and $module_version are not,
    # try loading the tarball passed first.
    if [[ $archive_location && ! $module && ! $module_version ]]; then
        load_tarball
    elif [[ $try_source_tree && ! $module && ! $module_version ]]; then
        add_source_tree "$try_source_tree"
    fi

    # Check that we have all the arguments
    check_module_args add

    # Do stuff for --rpm_safe_upgrade
    if [[ $rpm_safe_upgrade ]]; then
        local pppid=$(awk '/PPid:/ {print $2}' /proc/$PPID/status)
        local lock_name=$(mktemp_or_die $tmp_location/dkms_rpm_safe_upgrade_lock.$pppid.XXXXXX)
        echo "$module-$module_version" >> $lock_name
        ps -o lstart --no-headers -p $pppid 2>/dev/null >> $lock_name
    fi

    # Check that this module-version hasn't already been added
    if is_module_added "$module" "$module_version"; then
        die 3 $"DKMS tree already contains: $module-$module_version" \
            $"You cannot add the same module/version combo more than once."
    fi

    [[ $conf ]] || conf="$source_tree/$module-$module_version/dkms.conf"

    # Check that /usr/src/$module-$module_version exists
    if ! [[ -d $source_tree/$module-$module_version ]]; then
        die 2 $"Could not find module source directory." \
            $"Directory: $source_tree/$module-$module_version does not exist."
    fi

    # Check the conf file for sanity
    read_conf_or_die "$kernelver" "$arch" "$conf"

    # Create the necessary dkms tree structure
    echo $"Creating symlink $dkms_tree/$module/$module_version/source -> $source_tree/$module-$module_version"
    mkdir -p "$dkms_tree/$module/$module_version/build"
    ln -s "$source_tree/$module-$module_version" "$dkms_tree/$module/$module_version/source"

    # Run the post_add script
    run_build_script post_add "$post_add"
}

# Prepare a kernel source or include tree for compiling a module.
# Most modern-ish distros do not require this function at all,
# so it will be removed in a future release.
prepare_kernel()
{
    # $1 = kernel version to prepare
    # $2 = arch to prepare

    set_kernel_source_dir "$1"

    # Check that kernel-source exists
    _check_kernel_dir "$1" || {
    case "$running_distribution" in
        Debian* | Ubuntu* )
            die 1 $"Your kernel headers for kernel $1 cannot be found." \
                $"Please install the linux-headers-$1 package or use the --kernelsourcedir option to tell DKMS where it's located."
                ;;
        * )
            die 1 $"Your kernel headers for kernel $1 cannot be found at /lib/modules/$1/build or /lib/modules/$1/source." \
                $"You can use the --kernelsourcedir option to tell DKMS where it's located."
            ;;
    esac
    }

    if [ -f "$kernel_source_dir/.kernelvariables" ]; then
        export CC=$(echo -e "show-%:\n\t@echo \$(\$*)\ninclude $kernel_source_dir/.kernelvariables" | make -f - show-CC)
    else
        unset CC
    fi

    [[ $no_prepare_kernel ]] && return

    if [[ (! ( $(VER $1) < $(VER 2.6.5) ) || -d /etc/SuSEconfig) && \
        -d "$kernel_source_dir" && \
        -z "$ksourcedir_fromcli" ]]; then
        echo $""
        echo $"Kernel preparation unnecessary for this kernel. Skipping..."
        no_clean_kernel="no-clean-kernel"
        return 1
    fi

    # Prepare kernel for module build
    echo $""
    echo $"Preparing kernel $1 for module build:"
    echo $"(This is not compiling a kernel, just preparing kernel symbols)"
    cd $kernel_source_dir
    [[ -r .config ]] && {
        config_contents=$(cat .config)
        echo $"Storing current .config to be restored when complete"
    }

    # Set kernel_config
    if [[ -e /etc/redhat-release || -e /etc/fedora-release ]]; then
    # Note this also applies to VMware 3.x
    if [[ -z $kernel_config && -d $kernel_source_dir/configs ]]; then
        local kernel_trunc=${1%%-*}
        # Try a .config specific to whatever kernel we are running
        if [[ $1 =~ $rh_kernels && -e $kernel_source_dir/configs/kernel-$kernel_trunc-$2-${BASH_REMATCH[1]}.config ]]; then
            kernel_config="$kernel_source_dir/configs/kernel-$kernel_trunc-$2-${BASH_REMATCH[1]}.config"
        elif [[ -e $kernel_source_dir/configs/kernel-$kernel_trunc-$2.config ]]; then
            # If that one does not exist, try a generic one.
            kernel_config="$kernel_source_dir/configs/kernel-$kernel_trunc-$2.config"
        else
            # If that does not exist, fall back to no config file
            kernel_config=""
        fi
    fi
    elif [[ (-e /etc/SuSE-release || -d /etc/SuSEconfig) && -z $kernel_config && -d $kernel_source_dir/arch ]]; then
        local kernel_trunc=${1%%-*}
        case $2 in
            i586|i686)
                config_arch="i386"
                ;;
            *)
                config_arch=$2
                ;;
        esac
        for config_type in default smp bigsmp; do
            [[ $1 =~ $config_type ]] && kernel_config="$kernel_source_dir/arch/$config_arch/defconfig.$config_type"
            [[ -e $kernel_config ]] || kernel_config=""
        done
        [[ $kernel_config ]] || kernel_config="$kernel_source_dir/arch/$config_arch/defconfig.default"
        [[ -e $kernel_config ]] || kernel_config=""
    fi

    # Do preparation
    if [ -e /boot/vmlinuz.version.h ]; then
        echo $"Running UnitedLinux preparation routine"
        local kernel_config="/boot/vmlinuz.config"
        invoke_command "make mrproper" "make mrproper" background
        [[ $config_contents ]] && echo "$config_contents" > .config
        invoke_command "cp /boot/vmlinuz.version.h include/linux/version.h" "using /boot/vmlinux.version.h"
        invoke_command "cp -f $kernel_config .config" "using $kernel_config"
        invoke_command "make KERNELRELEASE=$1 cloneconfig" "make cloneconfig" background
        invoke_command "make -j$parallel_jobs CONFIG_MODVERSIONS=1 KERNELRELEASE=$1 dep" "make CONFIG_MODVERSIONS=1 dep" background
    elif grep -q rhconfig.h $kernel_source_dir/include/linux/{modversions,version}.h 2>/dev/null; then
        echo $"Running Red Hat style preparation routine"
        invoke_command "make clean" "make clean" background
        [[ $config_contents ]] && echo "$config_contents" > .config

        if [[ $kernel_config ]]; then
            echo $"using $kernel_config"
            cp -f "$kernel_config" .config
        elif [[ -e .config ]]; then
            warn $"Using $kernel_source_dir/.config" \
                $"(I hope this is the correct config for this kernel)"
        else
            warn $"Cannot find a .config file to prepare your kernel with." \
                $"Try using the --config option to specify where one can be found." \
                $"Your build will likely fail because of this."
        fi

        # Hack to workaround broken tmp_include_depends for Red Hat
        if grep -q "/usr/src/build" $kernel_source_dir/tmp_include_depends 2>/dev/null; then
            sed 's/\/usr\/src\/build\/.*\/install//g' $kernel_source_dir/tmp_include_depends > $kernel_source_dir/tmp_include_depends.new
            mv -f $kernel_source_dir/tmp_include_depends.new $kernel_source_dir/tmp_include_depends
        fi

        invoke_command "make KERNELRELEASE=$1 oldconfig" "make oldconfig" background
        kerneldoth_contents=$(cat /boot/kernel.h 2>/dev/null)
        invoke_command "/usr/lib/dkms/mkkerneldoth --kernelver $1 --targetarch $2 --output /boot/kernel.h" "running mkkerneldoth" background
    else
        echo $"Running Generic preparation routine"
        invoke_command "make mrproper" "make mrproper" background
        [[ $config_contents ]] && echo "$config_contents" > .config

        if [[ $kernel_config ]]; then
            echo $"using $kernel_config"
            cp -f "$kernel_config" .config
        elif [[ -e .config ]]; then
            warn $"using $kernel_source_dir/.config" \
                $"(I hope this is the correct config for this kernel)"
        else
            warn $"Warning! Cannot find a .config file to prepare your kernel with." \
                $"Try using the --config option to specify where one can be found." \
                $"Your build will likely fail because of this."
        fi

        invoke_command "make KERNELRELEASE=$1 oldconfig" "make oldconfig" background
        if [[ $(VER $1) < $(VER 2.5) ]]; then
            invoke_command "make -j$parallel_jobs KERNELRELEASE=$1 dep" "make dep" background
        else
            invoke_command "make -j$parallel_jobs KERNELRELEASE=$1 prepare-all scripts" "make prepare-all" background
        fi
    fi
    cd - >/dev/null
}

# Get ready to build a module that has been registered with DKMS.
prepare_build()
{
    # If the module has not been added, try to add it.
    is_module_added "$module" "$module_version" || add_module

    set_kernel_source_dir "$kernelver"
    local base_dir="$dkms_tree/$module/$module_version/$kernelver/$arch"

    # Check that the right arguments were passed
    check_module_args build

    # Check that the module has not already been built for this kernel
    [[ -d $base_dir ]] && die 3 \
        $"This module/version has already been built on: $kernelver" \
        $"Directory $base_dir already exists. Use the dkms remove function before trying to build again."

    # Read the conf file
    set_module_suffix "$kernelver"
    read_conf_or_die "$kernelver" "$arch"

    # Error out if build_exclude is set
    [[ $build_exclude ]] && die 9 \
        $"The $base_dir/dkms.conf for module $module includes a BUILD_EXCLUSIVE directive which does not match this kernel/arch."\
	$"The $base_dir/dkms.conf for module $module includes a BUILD_EXCLUSIVE directive which does not match this kernel/arch/config."\
        $"This indicates that it should not be built."

    # Error out if source_tree is basically empty (binary-only dkms tarball w/ --force check)
    (($(ls $dkms_tree/$module/$module_version/source | wc -l | awk {'print $1'}) < 2)) && die 8 \
        $"The directory $dkms_tree/$module/$module_version/source/ does not appear to have module source located within it."\
        $"Build halted."

    prepare_kernel "$kernelver" "$arch"

    # Set up temporary build directory for build
    rm -rf "$dkms_tree/$module/$module_version/build"
    cp -a "$dkms_tree/$module/$module_version/source/" "$dkms_tree/$module/$module_version/build"

    cd "$dkms_tree/$module/$module_version/build"

    # Apply any patches
    for p in "${patch_array[@]}"; do
        [[ ! -e $dkms_tree/$module/$module_version/build/patches/$p ]] && \
            report_build_problem 5 \
            $" Patch $p as specified in dkms.conf cannot be" \
            $"found in $dkms_tree/$module/$module_version/build/patches/."
        invoke_command "patch -p1 < ./patches/$p" "applying patch $p" || \
            report_build_problem 6 $"Application of patch $p failed." \
            $"Check $dkms_tree/$module/$module_version/build/ for more information."
    done

    if [[ -e $kernel_source_dir/.config ]]; then
        cc=$(sed -n 's|^CONFIG_CC_VERSION_TEXT="\([^ ]*\) .*"|\1|p' $kernel_source_dir/.config)
        if command -v "$cc" >/dev/null; then
            export CC="$cc"
        fi
    fi

    # Run the pre_build script
    run_build_script pre_build "$pre_build"
}

# Build our previously prepared source tree.  prepare_build must be called
# before calling this function.
do_build()
{
    local base_dir="$dkms_tree/$module/$module_version/$kernelver/$arch"
    echo $""
    echo $"Building module:"

    invoke_command "$clean" "cleaning build area" background
    echo $"DKMS make.log for $module-$module_version for kernel $kernelver ($arch)" >> "$dkms_tree/$module/$module_version/build/make.log"
    date >> "$dkms_tree/$module/$module_version/build/make.log"
    local the_make_command="${make_command/#make/make -j$parallel_jobs KERNELRELEASE=$kernelver}"

    invoke_command "{ $the_make_command; } >> $dkms_tree/$module/$module_version/build/make.log 2>&1" "$the_make_command" background || \
        report_build_problem 10 $"Bad return status for module build on kernel: $kernelver ($arch)" \
        $"Consult $dkms_tree/$module/$module_version/build/make.log for more information."

    # Make sure all the modules built successfully
    for ((count=0; count < ${#built_module_name[@]}; count++)); do
        [[ -e ${built_module_location[$count]}${built_module_name[$count]}$module_uncompressed_suffix ]] && continue
        report_build_problem 7 \
            $" Build of ${built_module_name[$count]}$module_uncompressed_suffix failed for: $kernelver ($arch)" \
            $"Make sure the name of the generated module is correct and at the root of the" \
            $"build directory, or consult make.log in the build directory" \
            $"$dkms_tree/$module/$module_version/build/ for more information."
    done
    cd - >/dev/null

    # Build success, so create DKMS structure for a built module
    mkdir -p "$base_dir/log"
    [[ $kernel_config ]] && cp -f "$kernel_config" "$base_dir/log/"
    mv -f "$dkms_tree/$module/$module_version/build/make.log" "$base_dir/log/make.log" 2>/dev/null

    # Save a copy of the new module
    mkdir "$base_dir/module" >/dev/null
    for ((count=0; count < ${#built_module_name[@]}; count++)); do
        [[ ${strip[$count]} != no ]] && strip -g "$dkms_tree/$module/$module_version/build/${built_module_location[$count]}${built_module_name[$count]}$module_uncompressed_suffix"

        if [ -n "${sign_tool}" ]; then
            echo $"Signing module $dkms_tree/$module/$module_version/build/${built_module_location[$count]}${built_module_name[$count]}$module_uncompressed_suffix"
            echo $""
            run_sign_tool "${sign_tool}" "$dkms_tree/$module/$module_version/build/${built_module_location[$count]}${built_module_name[$count]}$module_uncompressed_suffix"
        fi

        if [ "$module_compressed_suffix" = ".gz" ]; then
            gzip -9f "$dkms_tree/$module/$module_version/build/${built_module_location[$count]}${built_module_name[$count]}$module_uncompressed_suffix"
        elif [ "$module_compressed_suffix" = ".xz" ]; then
            xz -f "$dkms_tree/$module/$module_version/build/${built_module_location[$count]}${built_module_name[$count]}$module_uncompressed_suffix"
        elif [ "$module_compressed_suffix" = ".zst" ]; then
            zstd -q -f -T0 -20 --ultra "$dkms_tree/$module/$module_version/build/${built_module_location[$count]}${built_module_name[$count]}$module_uncompressed_suffix"
        fi
        cp -f "$dkms_tree/$module/$module_version/build/${built_module_location[$count]}${built_module_name[$count]}$module_suffix" \
            "$base_dir/module/${dest_module_name[$count]}$module_suffix" >/dev/null
    done

    # Run the post_build script
    run_build_script post_build "$post_build"
}

# Clean up after a build.
clean_build()
{
    # Run the clean commands
    cd "$dkms_tree/$module/$module_version/build"
    invoke_command "$clean" "cleaning build area" background
    cd - >/dev/null

    if [[ ! ( $(VER $kernelver) < $(VER 2.6.6) ) && \
       -d $kernel_source_dir && \
       ! -h $kernel_source_dir && \
       ! $ksourcedir_fromcli ]]; then
        echo $"Kernel cleanup unnecessary for this kernel.  Skipping..."
    elif [[ ! $no_clean_kernel ]]; then
        cd "$kernel_source_dir"
        [[ $kerneldoth_contents ]] || invoke_command "make mrproper" "cleaning kernel tree (make mrproper)" background
        [[ $config_contents ]] || echo "$config_contents" > .config
        [[ $kerneldoth_contents ]] && echo "$kerneldoth_contents" > /boot/kernel.h
        cd - >/dev/null
    fi

    # Clean the build directory
    rm -rf "$dkms_tree/$module/$module_version/build"
}

sign_build()
{
    [[ -x "$(command -v kmodsign)" && -d "/var/lib/shim-signed/mok/" ]] || return
    local base_dir="$dkms_tree/$module/$module_version/$kernelver/$arch"
    if type update-secureboot-policy >/dev/null 2>&1; then
        echo $"Signing module:"
        SHIM_NOTRIGGER=y update-secureboot-policy --new-key
        for ko in `find "$base_dir/module/" -name "*.ko" -print`;
        do
            echo " - $ko"
            kmodsign sha512 \
                /var/lib/shim-signed/mok/MOK.priv \
                /var/lib/shim-signed/mok/MOK.der \
                "$ko"
        done
        update-secureboot-policy --enroll-key
    fi
}

build_module()
{
    prepare_build
    do_build
    sign_build
    clean_build
}

# Force the installation of a module if this is listed
# in the files in $forced_modules_dir, if any
force_installation()
{
    forced_modules_dir="/usr/share/dkms/modules_to_force_install"
    to_force=""
    if [ -d $forced_modules_dir ]; then
        for elem in $forced_modules_dir/*; do
            if [ -e $elem ]; then
                to_force="$to_force $(cat $elem)"
            fi
        done

        for elem in $to_force; do
            if [ "${1}" = "${elem}" ]; then
                echo "force"
                return 0
            elif [ "${1}_version-override" = "${elem}" ]; then
                echo "version-override"
                return 0
            fi
        done
    fi
    return 1
}

# Install a previously built module
# There are huge swaths of code here that special-case for various distros.
# They should be split into their own functions.
install_module()
{
    # If the module has not been built, try to build it first.
    is_module_built "$module" "$module_version" "$kernelver" "$arch" || build_module
    local base_dir="$dkms_tree/$module/$module_version/$kernelver/$arch"
    check_module_args install

    # Save the status of $force
    tmp_force="$force"

    # If the module is set to be force-installed
    local ret=$(force_installation $module)
    if [[ "$ret" == "force" ]];then
        force="true"
        echo "Forcing installation of $module"
    elif [[ "$ret" == "version-override" ]];then
        force_version_override="true"
        echo "Forcing version override of $module"
    fi
    # Make sure that kernel exists to install into
    [[ -e $install_tree/$kernelver ]] || die 6 \
        $"The directory $install_tree/$kernelver doesn't exist." \
        $"You cannot install a module onto a non-existant kernel."

    # Read the conf file
    read_conf_or_die "$kernelver" "$arch"

    # Check that its not already installed (kernel symlink)
    is_module_installed "$module" "$module_version" "$kernelver" "$arch" && die 5 \
        $"This module/version combo is already installed for kernel $kernelver ($arch)."

    # If upgrading using rpm_safe_upgrade, go ahead and force the install
    # else we can wind up with the first half of an upgrade failing to install anything,
    # while the second half of the upgrade, the removal, then succeeds, leaving us with
    # nothing installed.
    [[ $rpm_safe_upgrade ]] && force="true"

    # Save the original_module if one exists, none have been saved before, and this is the first module for this kernel
    local lib_tree="$install_tree/$kernelver"
    local count
    for ((count=0; count < ${#built_module_name[@]}; count++)); do
    echo $""
    echo $"${dest_module_name[$count]}$module_suffix:"
    # Check this version against what is already in the kernel
    check_version_sanity "$kernelver" "$arch" "$obsolete_by" "${dest_module_name[$count]}" || continue

    if ((count == 0)) && ! run_build_script pre_install "$pre_install" && ! [[ $force ]]; then
        die 101 $"pre_install failed, aborting install." \
            $"You may override by specifying --force."
    fi
    local m=${dest_module_name[$count]}
    local installed_modules=$(find_module "$lib_tree" "$m")
    local module_count=${#installed_modules[@]}
    echo $" - Original module"
    local original_copy=$(compressed_or_uncompressed "$dkms_tree/$module/original_module/$kernelver/$arch" "$m")
    if [[ -L $dkms_tree/$module/kernel-$kernelver-$arch &&
        -n "$original_copy" ]]; then
        echo $"   - An original module was already stored during a previous install"
    elif ! [[ -L $dkms_tree/$module/kernel-$kernelver-$arch ]]; then
        local archive_pref1=$(compressed_or_uncompressed "$lib_tree/extra" "$m")
        local archive_pref2=$(compressed_or_uncompressed "$lib_tree/updates" "$m")
        local archive_pref3=$(compressed_or_uncompressed "$lib_tree${dest_module_location[$count]}" "$m")
        local archive_pref4=""
        ((module_count == 1)) && archive_pref4=${installed_modules[0]}
        local original_module=""
        local found_orginal=""
        for original_module in $archive_pref1 $archive_pref2 $archive_pref3 $archive_pref4; do
            [[ -f $original_module ]] || continue
            case "$running_distribution" in
                Debian* | Ubuntu* )
                    ;;
                *)
                echo $"   - Found $original_module"
                echo $"   - Storing in $dkms_tree/$module/original_module/$kernelver/$arch/"
                echo $"   - Archiving for uninstallation purposes"
                mkdir -p "$dkms_tree/$module/original_module/$kernelver/$arch"
                mv -f "$original_module" "$dkms_tree/$module/original_module/$kernelver/$arch/"
                ;;
            esac
            found_original="yes"
            break
        done
        if [[ ! $found_original ]] && ((module_count > 1)); then
            echo $"   - Multiple original modules exist but DKMS does not know which to pick"
            echo $"   - Due to the confusion, none will be considered during a later uninstall"
        elif [[ ! $found_original ]]; then
            echo $"   - No original module exists within this kernel"
        fi
    else
        echo $"   - This kernel never originally had a module by this name"
    fi

    if ((module_count > 1)); then
        echo $" - Multiple same named modules!"
        echo $"   - $module_count named $m$module_suffix in $lib_tree/"
        case "$running_distribution" in
            Debian* | Ubuntu* )
                ;;
            *)
                echo $"   - All instances of this module will now be stored for reference purposes ONLY"
                echo $"   - Storing in $dkms_tree/$module/original_module/$kernelver/$arch/collisions/"
                ;;
        esac
        for module_dup in $(find_module "$lib_tree" "$m"); do
            dup_tree="${module_dup#$lib_tree}";
            dup_name="${module_dup##*/}"
            dup_tree="${dup_tree/${dup_name}}"
            case "$running_distribution" in
                Debian* | Ubuntu* )
                    ;;
                *)
                   echo $"     - Stored $module_dup"
                   mkdir -p "$dkms_tree/$module/original_module/$kernelver/$arch/collisions/$dup_tree"
                   mv -f $module_dup "$dkms_tree/$module/original_module/$kernelver/$arch/collisions/$dup_tree"
                   ;;
            esac
        done
    fi

    # Copy module to its location
    echo $" - Installation"
    echo $"   - Installing to $install_tree/$kernelver${dest_module_location[$count]}/"
    mkdir -p $install_tree/$kernelver${dest_module_location[$count]}
    [[ $symlink_modules ]] && symlink="-s"
    local toinstall=$(compressed_or_uncompressed "$base_dir/module" "$m")
    cp -f $symlink "$toinstall" "$install_tree/$kernelver${dest_module_location[$count]}/${toinstall##*/}"

    done

    # Create the kernel-<kernelver> symlink to designate this version as active
    rm -f "$dkms_tree/$module/kernel-$kernelver-$arch" 2>/dev/null
    ln -s "$module_version/$kernelver/$arch" "$dkms_tree/$module/kernel-$kernelver-$arch" 2>/dev/null

    # Add to kabi-tracking
	if [ -z "$NO_WEAK_MODULES" ]; then
		if [[ ${weak_modules} ]]; then
			echo $"Adding any weak-modules"
			list_each_installed_module "$module" "$kernelver" "$arch" | ${weak_modules} ${weak_modules_no_initrd} --add-modules
		fi
	fi

    # Run the post_install script
    run_build_script post_install "$post_install"

    # Make modules.conf changes as necessary
    echo $""
    moduleconfig_add "$kernelver"
    etc_sysconfig_kernel_modify "add"

    invoke_command "do_depmod $kernelver" "depmod" background || {
        do_uninstall "$kernelver" "$arch"
        die 6 $"Problems with depmod detected. Automatically uninstalling this module." \
            $"Install Failed (depmod problems). Module rolled back to built state."
            exit 6
    }

    # Do remake_initrd things (save old initrd)
    [[ $remake_initrd ]] && ! make_initrd "$kernelver" "$arch" backup && {
        do_uninstall "$kernelver" "$arch"
        die 7 $"Problems with mkinitrd detected. Automatically uninstalling this module." \
            $"Install Failed (mkinitrd problems). Module rolled back to built state."
    }

    # Restore the status of $force
    force="$tmp_force"
}

# List each kernel object that has been installed for a particular module.
list_each_installed_module()
{
    # $1 = module
    # $2 = kernel version
    # $3 = arch
    local count
    local real_dest_module_location
    local mod
    for ((count=0; count < ${#built_module_name[@]}; count++)); do
        real_dest_module_location="$(find_actual_dest_module_location $1 $count $2 $3)"
        mod=$(compressed_or_uncompressed "$install_tree/$2${real_dest_module_location}" "${dest_module_name[$count]}")
        echo "$mod"
    done
}

is_module_added() {
    [[ $1 && $2 ]] || return 1
    [[ -d $dkms_tree/$1/$2 ]] || return 2
    [[ -L $dkms_tree/$1/$2/source || -d $dkms_tree/$1/$2/source ]];
}

is_module_built() {
    [[ $1 && $2 && $3 && $4 ]] || return 1
    local d="$dkms_tree/$1/$2/$3/$4" m=''
    [[ -d $d/module ]] || return 1
    local default_conf="$dkms_tree/$1/$2/source/dkms.conf"
    # If a custom dkms.conf was specified use it, otherwise use the default one.
    local real_conf="${conf:-${default_conf}}"
    read_conf_or_die "$3" "$4" "$real_conf"
    set_module_suffix "$3"
    for m in "${dest_module_name[@]}"; do
        local t=$(compressed_or_uncompressed "$d/module" "$m")
        test -n "$t" || return 1
    done
}

# This assumes we have already checked to see if the module has been built.
_is_module_installed() {
    [[ $1 && $2 && $3 && $4 ]] || return 1
    local d="$dkms_tree/$1/$2/$3/$4"
    local k="$dkms_tree/$1/kernel-$3-$4"
    [[ -L $k && $(readlink -f $k) = $d ]]
}

# This does not.
is_module_installed() { is_module_built "$@" && _is_module_installed "$@"; }

maybe_add_module() (
    is_module_added "$1" "$2" && {
        echo $"Module $1/$2 already added."
        return 0
    }
    module="$1" module_version="$2" add_module
)

maybe_build_module() (
    is_module_built "$1" "$2" "$3" "$4" && {
        echo $"Module $1/$2 already built for kernel $3 ($4)."
        return 0
    }
    module="$1" module_version="$2" kernelver="$3" arch="$4" build_module
)

maybe_install_module() (
    is_module_installed "$1" "$2" "$3" "$4" && {
        echo $"Module $1/$2 already installed on kernel $3 ($4)."
        return 0
    }
    module="$1" module_version="$2" kernelver="$3" arch="$4" install_module
)

build_modules() {
    local i=0
    for ((i=0; i < ${#kernelver[@]}; i++)); do
        maybe_build_module "$module" "$module_version" "${kernelver[$i]}" "${arch[$i]}"
    done
}

install_modules() {
    local i=0
    for ((i=0; i < ${#kernelver[@]}; i++)); do
        maybe_install_module "$module" "$module_version" "${kernelver[$i]}" "${arch[$i]}"
    done
}

check_module_exists() {
    is_module_added "$module" "$module_version" && return
    die 2 $"DKMS tree does not contain: $module-$module_version" \
        $"Build cannot continue without the proper tree."
}

possible_dest_module_locations()
{
    # $1 = count
    # There are two places an installed module may really be:
    # 1) "$install_tree/$kernelver/${dest_module_location[$count]}/${dest_module_name[$count]}$module_suffix"
    # 2) "$install_tree/$kernelver/${DEST_MODULE_LOCATION[$count]}/${dest_module_name[$count]}$module_suffix"
    # override_dest_module_location() is what controls whether or not they're the same.

    local location
    location[0]="${dest_module_location[$count]}"
    [[ ${DEST_MODULE_LOCATION[$count]} != ${dest_module_location[$count]} ]] && \
    location[1]="${DEST_MODULE_LOCATION[$count]}"

    echo "${location[@]}"
}

find_actual_dest_module_location()
{
    local module="$1"
    local count="$2"
    local kernelver="$3"
    local arch="$4"
    local locations="$(possible_dest_module_locations $count)"
    local l
    local dkms_owned
    local installed
    dkms_owned=$(compressed_or_uncompressed "${dkms_tree}/${module}/kernel-${kernelver}-${arch}/module" "${dest_module_name[$count]}")

    for l in $locations; do
        installed=$(compressed_or_uncompressed "${install_tree}/${kernelver}${l}" "${dest_module_name[${count}]}")
        if [[ -n "${installed}" ]] && diff "${dkms_owned}" "${installed}" > /dev/null 2>&1; then
            echo "${l}"
            return 0
        fi
    done

}

# Remove compiled DKMS modules from any kernels they are installed in.
do_uninstall()
{
    # $1 = kernel version
    # $2 = arch

    echo $"Module $module-$module_version for kernel $1 ($2)."

    set_module_suffix "$1"

    # If kernel-<kernelver> symlink points to this module, check for original_module and put it back
    local was_active=""
    local kernel_symlink=$(readlink -f "$dkms_tree/$module/kernel-$1-$2")
    local real_dest_module_location
    if [[ $kernel_symlink = $dkms_tree/$module/$module_version/$1/$2 ]]; then
        was_active="true"
        echo $"Before uninstall, this module version was ACTIVE on this kernel."
        # remove kabi-tracking if last instance removed
		if [ -z "$NO_WEAK_MODULES" ]; then
			if [[ ${weak_modules} ]] && (module_status_built $module $module_version |grep -q "installed"); then
				echo $"Removing any linked weak-modules"
				list_each_installed_module "$module" "$1" "$2" | ${weak_modules} ${weak_modules_no_initrd} --remove-modules
			fi
		fi

    for ((count=0; count < ${#built_module_name[@]}; count++)); do
        real_dest_module_location="$(find_actual_dest_module_location $module $count $1 $2)"
        echo $""
        echo $"${dest_module_name[$count]}$module_suffix:"
        echo $" - Uninstallation"
        echo $"   - Deleting from: $install_tree/$1${real_dest_module_location}/"
        rm -f "$install_tree/$1${real_dest_module_location}/${dest_module_name[$count]}$module_uncompressed_suffix"*
        dir_to_remove="${real_dest_module_location#/}"
        while [ "${dir_to_remove}" != "${dir_to_remove#/}" ]; do
            dir_to_remove="${dir_to_remove#/}"
        done
        (if cd "$install_tree/$1"; then rpm -qf "${dir_to_remove}" >/dev/null 2>&1 || rmdir -p --ignore-fail-on-non-empty "${dir_to_remove}"; fi || true)
        echo $" - Original module"
        local origmod=$(compressed_or_uncompressed "$dkms_tree/$module/original_module/$1/$2" "${dest_module_name[$count]}")
        if [[ -n "$origmod" ]]; then
            case "$running_distribution" in
                Debian* | Ubuntu* )
                    ;;
                *)
                    echo $"   - Archived original module found in the DKMS tree"
                    echo $"   - Moving it to: $install_tree/$1${DEST_MODULE_LOCATION[$count]}/"
                    mkdir -p "$install_tree/$1${DEST_MODULE_LOCATION[$count]}/"
                    mv -f "$origmod" "$install_tree/$1${DEST_MODULE_LOCATION[$count]}/" 2>/dev/null
                    ;;
            esac
            else
            echo $"   - No original module was found for this module on this kernel."
            echo $"   - Use the dkms install command to reinstall any previous module version."

            # Remove modules_conf entries from /etc/modules.conf if remake_initrd is set or if this is last instance removed
            if [[ $remake_initrd ]] || (do_status $module $module_version | grep -q "installed"); then
                echo $""
                moduleconfig_remove "$1"
            fi
        fi
    done
    rm -f "$dkms_tree/$module/kernel-$1-$2"
    else
        echo $"This module version was INACTIVE for this kernel."
    fi

    # Run the post_remove script
    run_build_script post_remove "$post_remove"

    # Run depmod because we changed /lib/modules
    invoke_command "do_depmod $1" "depmod" background

    # Do remake_initrd things (remake initrd)
    if [[ $remake_initrd && $was_active ]] && ! make_initrd "$1" "$2" ''; then
        warn $"There was a problem remaking your initrd.  You must manually remake it" \
            $"before booting into this kernel."
    fi

    # Delete the original_module if nothing for this kernel is installed anymore
    if [[ $was_active && -d $dkms_tree/$module/original_module/$1/$2 && ! -d $dkms_tree/$module/original_module/$1/$2/collisions ]]; then
        echo $""
        echo $"Removing original_module from DKMS tree for kernel $1 ($2)"
        rm -rf "$dkms_tree/$module/original_module/$1/$2" 2>/dev/null
        [[ $(find $dkms_tree/$module/original_module/$1/* -maxdepth 0 -type d 2>/dev/null) ]] || rm -rf "$dkms_tree/$module/original_module/$1"
    elif [[ $was_active && -d $dkms_tree/$module/original_module/$1/$2/collisions ]]; then
        echo $""
        echo $"Keeping directory $dkms_tree/$module/original_module/$1/$2/collisions/"
        echo $"for your reference purposes.  Your kernel originally contained multiple"
        echo $"same-named modules and this directory is now where these are located."
    fi
    [[ $(find $dkms_tree/$module/original_module/* -maxdepth 0 -type d 2>/dev/null) ]] || rm -rf "$dkms_tree/$module/original_module"

    # Re-add entries to modules.conf if this module/version is still installed on another kernel
    # But only do this if it was just ACTIVE on the kernel we just uninstalled from
    [[ $was_active && $remake_initrd ]] && do_status $module $module_version | grep -q "installed" && moduleconfig_add "$1"
}

module_is_added_or_die()
{
    is_module_added "$module" "$module_version" || die 3 \
        $"The module/version combo: $module-$module_version is not located in the DKMS tree."
}

module_is_built_or_die()
{
    is_module_built "$module" "$module_version" "$1" "$2" || die 4 \
        $"There is no instance of $module $module_version for kernel $1 ($2) located in the DKMS tree."

}

module_is_installed_or_die()
{
    is_module_installed "$module" "$module_version" "$1" "$2" || die 4 \
        $"The module $module $module_version is not currently installed." \
        $"This module is not currently ACTIVE for kernel $1 ($2)."
}

# Check our preconditions, and then let do_install do all the hard work.
uninstall_module()
{
    # Check that the right arguments were passed
    check_module_args uninstall

    # Check that $module is in the dkms tree
    module_is_added_or_die

    local i
    for ((i=0; i < ${#kernelver[@]}; i++)); do
        # Only do stuff if module/module version is currently installed
        module_is_installed_or_die "${kernelver[$i]}" "${arch[$i]}"
        do_uninstall "${kernelver[$i]}" "${arch[$i]}"
    done
}

do_unbuild()
{
    # Delete or "unbuild" the $kernel_version/$arch_used part of the tree
    rm -rf "$dkms_tree/$module/$module_version/$1/$2"
    [[ $(find $dkms_tree/$module/$module_version/$1/* -maxdepth 0 -type d 2>/dev/null) ]] || \
        rm -rf "$dkms_tree/$module/$module_version/$1"
}

# Remove the build module, w/o removing/unregistering it.
# This uninstalls any installed modules along the way
unbuild_module()
{
    # Check that the right arguments were passed
    check_module_args unbuild

    # Check that $module is in the dkms tree
    module_is_added_or_die

    local i
    for ((i=0; i < ${#kernelver[@]}; i++)); do
        # Only do stuff if module/module version is currently built
        module_is_built_or_die "${kernelver[$i]}" "${arch[$i]}"

        do_uninstall "${kernelver[$i]}" "${arch[$i]}"

        do_unbuild "${kernelver[$i]}" "${arch[$i]}"
    done
}

# Unregister a DKMS module.  This uninstalls any installed modules along the way.
remove_module()
{
    # Check that the right arguments were passed
    check_module_args remove

    # Do --rpm_safe_upgrade check (exit out and don't do remove if inter-release RPM upgrade scenario occurs)
    if [[ $rpm_safe_upgrade ]]; then
        local pppid=$(awk '/PPid:/ {print $2}' /proc/$PPID/status)
        local time_stamp=$(ps -o lstart --no-headers -p $pppid 2>/dev/null)
        for lock_file in $tmp_location/dkms_rpm_safe_upgrade_lock.$pppid.*; do
            [[ -f $lock_file ]] || continue
            lock_head=$(head -n 1 $lock_file 2>/dev/null)
            lock_tail=$(tail -n 1 $lock_file 2>/dev/null)
            [[ $lock_head = $module-$module_version && $time_stamp && $lock_tail = $time_stamp ]] || continue
            rm -f $lock_file
            die 0 $"Remove cancelled because --rpm_safe_upgrade scenario detected."
        done
    fi

    # Check that $module is in the dkms tree
    module_is_added_or_die

    local i
    for ((i=0; i < ${#kernelver[@]}; i++)); do
        # Make sure its there first before removing
        module_is_built_or_die "${kernelver[$i]}" "${arch[$i]}"

        do_uninstall "${kernelver[$i]}" "${arch[$i]}"

        do_unbuild "${kernelver[$i]}" "${arch[$i]}"
    done

    # Delete the $module_version part of the tree if no other $module_version/$kernel_version dirs exist
    if ! find $dkms_tree/$module/$module_version/* -maxdepth 0 -type d 2>/dev/null | egrep -qv "(build|tarball|driver_disk|rpm|deb|source)$"; then
        echo $"Deleting module $module-$module_version completely from the DKMS tree."
        rm -rf "$dkms_tree/$module/$module_version"
    fi

    # Get rid of any remnant directories if necessary
    if (($(ls "$dkms_tree/$module" | wc -w | awk '{print $1}') == 0)); then
        rm -rf "$dkms_tree/$module" 2>/dev/null

        # Its now safe to completely remove references in /etc/sysconfig/kernel for SuSE
        etc_sysconfig_kernel_modify "delete"
    fi
}

# Given a kernel object, figure out which DKMS module it is from.
find_module_from_ko()
{
    local ko="$1"
    local basename_ko="${ko##*/}"
    local module
    local kernellink

    for kernellink in "$dkms_tree"/*/kernel-*; do
        [[ -L $kernellink ]] || continue
        module=${kernellink#$dkms_tree/}
        module=${module%/kernel-*}
        diff "$kernellink/module/${basename_ko}" "${ko}" >/dev/null 2>&1 || continue
        rest=$(readlink $kernellink)
        echo "$module/$rest"
        return 0
    done
    return 1
}

# Check to see if modules meeting the passed parameters are weak-installed.
# This function's calling convention is different from the usual DKMS status
# checking functions -- the kernel version we usually have is the one we are currently
# running on, not necessarily the one we compiled the module for.
module_status_weak() {
    # $1 = module, $2 = module version, $3 = kernel version weak installed to,
    # $4 = kernel arch, $5 = kernel version built for
	[ -z "$NO_WEAK_MODULES" ] || return 1
    [[ $weak_modules ]] || return 1
    local m v k a kern weak_ko mod installed_ko f ret=1 oifs=$IFS
    local -A already_found
    for weak_ko in "$install_tree/"*/weak-updates/*; do
        [[ -e $weak_ko ]] || continue
        [[ -L $weak_ko ]] && installed_ko="$(readlink -f "$weak_ko")" || continue
        IFS=/ read m v k a < <(IFS=$oifs find_module_from_ko "$weak_ko") || continue
        kern=${weak_ko#$install_tree/}
        kern=${kern%/weak-updates/*}
        [[ $m = ${1:-*} && $v = ${2:-*} && $k = ${5:-*} && $a = ${4:-*} && $kern = ${3:-*} ]] || continue
	already_found[$m/$v/$kern/$a/$k]+=${weak_ko##*/}" "
    done
    # Check to see that all ko's are present for each module
    for mod in ${!already_found[@]}; do
	IFS=/ read m v k a kern <<< "$mod"
	# ensure each module is weak linked
	for installed_ko in $(find $dkms_tree/$m/$v/$kern/$a/module -type f); do
	    [[ ${already_found[$mod]} != *"$installed_ko"* ]] && continue 2
	done
        ret=0
        echo "installed-weak $mod"
    done
    return $ret
}

# Print the requested status lines for weak-installed modules.
do_status_weak()
{
    local mvka m v k a kern status
    while read status mvka; do
        IFS=/ read m v k a kern <<< "$mvka"
        echo "$m, $v, $k, $a: installed-weak from $kern"
    done < <(module_status_weak "$@")
}

# Spit out all the extra status information that people running DKMS are
# interested in, but that the DKMS internals do not usually care about.
module_status_built_extra() (
    set_module_suffix "$3"
    read_conf "$3" "$4" "$dkms_tree/$1/$2/source/dkms.conf"
    [[ -d $dkms_tree/$1/original_module/$3/$4 ]] && echo -n " (original_module exists)"
    for ((count=0; count < ${#dest_module_name[@]}; count++)); do
        tree_mod=$(compressed_or_uncompressed "$dkms_tree/$1/$2/$3/$4/module" "${dest_module_name[$count]}")
        if ! [[ -n "$tree_mod" ]]; then
            echo -n " (WARNING! Missing some built modules!)"
        elif _is_module_installed "$@"; then
            real_dest="$(find_actual_dest_module_location "$1" $count "$3" "$4")"
            real_dest_mod=$(compressed_or_uncompressed "$install_tree/$3${real_dest}" "${dest_module_name[$count]}")
            if ! diff -q "$tree_mod" "$real_dest_mod" >/dev/null 2>&1; then
                echo -n " (WARNING! Diff between built and installed module!)"
            fi
        fi
    done
)

# Return a list of all the modules that are either built or installed.
# This and module_status do some juggling of $IFS to ensure that
# we do not get word splitting where it would be inconvenient.
module_status_built() {
    local ret=1 directory ka k a state oifs="$IFS" IFS=''
    for directory in "$dkms_tree/$1/$2/"${3:-+([0-9]).*}/${4:-*}; do
        IFS="$oifs"
        ka="${directory#$dkms_tree/$1/$2/}"
        k="${ka%/*}"
        a="${ka#*/}"
        is_module_built "$1" "$2" "$k" "$a" || continue
        ret=0
        state="built"
        _is_module_installed "$1" "$2" "$k" "$a" && state="installed"
        echo "$state $1/$2/$k/$a"
        IFS=''
    done
    IFS="$oifs"
    return $ret
}

# Return the status of all modules that have been added, built, or installed.
module_status() {
    local oifs="$IFS" IFS='' mv m v directory ret=1
    for directory in "$dkms_tree/"${1:-*}/${2:-*}; do
        IFS="$oifs"
        mv="${directory#$dkms_tree/}"
        m="${mv%/*}"
        v="${mv#*/}"
        is_module_added "$m" "$v" || continue
        ret=0
        module_status_built "$m" "$v" "$3" "$4" || echo "added $m/$v"
        IFS=''
    done
    IFS="$oifs"
    return $ret
}

# Print out the status in the format that people who call DKMS expect.
# Internal callers should use the module_status functions, as their output
# is easier to parse.
do_status() {
    local status mvka m v k a
    while read status mvka; do
        IFS=/ read m v k a <<< "$mvka"
        case $status in
            added)
                echo "$m/$v: $status"
                ;;
            built|installed)
                echo -n "$m/$v, $k, $a: $status"
                module_status_built_extra "$m" "$v" "$k" "$a"
                echo
                ;;
        esac
    done < <(module_status "$@")
}

# Show all our status in the format that external callers expect, even
# though it is slightly harder to parse.
show_status()
{
    local j state_array
    if ((${#kernelver[@]} == 0)); then
        do_status "$module" "$module_version" "$kernelver" "$arch"
        do_status_weak "$module" "$module_version" "$kernelver" "$arch"
    else
    for ((j=0; j < ${#kernelver[@]}; j++)); do
        do_status "$module" "$module_version" "${kernelver[$j]}" "${arch[$j]}"
        do_status_weak "$module" "$module_version" "${kernelver[$j]}" "${arch[$j]}"
    done
    fi
}

create_temporary_trees()
{
    [[ $module || $module_version || ! -r dkms.conf ]] && return 0

    . dkms.conf
    module="$PACKAGE_NAME"
    module_version="$PACKAGE_VERSION"

    source_tree=$(mktemp_or_die -d)
    dkms_tree=$(mktemp_or_die -d)

    local source_tree_dir="$source_tree/$PACKAGE_NAME-$PACKAGE_VERSION"
    mkdir -p "$source_tree_dir"
    cp -a * "$source_tree_dir" # intentionally skip .git or .hg
    add_module
    temporary_trees_del_command="rm -rf $source_tree $dkms_tree"
}

delete_temporary_trees()
{
    [[ $temporary_trees_del_command ]] || return 0
    $temporary_trees_del_command
    module=
    module_version=
    source_tree=
    dkms_tree=
    temporary_trees_del_command=
}

in_temporary_trees()
{
    [[ $temporary_trees_del_command ]]
}

media_valid()
{
    local mrx='^(floppy|iso|tar)$'
    [[ $media =~ $mrx ]]
}

make_driver_disk_floppy()
{
    local image_name="$1"
    local source_dir="$2"
    local file
    local fs='ext2'
    [[ $distro = redhat* ]] && fs='vfat'

    rm -f "$image_name"
    invoke_command "dd if=/dev/zero of=$image_name bs=$(($size/20))k count=20" "making a blank floppy image" background
    case $fs in
        vfat)
            invoke_command "mkdosfs $image_name" "mkdosfs" background
            ;;
        ext2)
            invoke_command "mke2fs -F $image_name" "mke2fs" background
            ;;
    esac

    local mntdir=$(mktemp_or_die -d $tmp_location/dkms.XXXXXX)
    invoke_command "mount -o loop -t $fs $image_name $mntdir >/dev/null 2>&1" "loopback mounting disk image"
    [[ -d $mntdir/lost+found ]] && rmdir "$mntdir/lost+found"
    invoke_command "cp -r $source_dir/* $mntdir/" "  copying files to floppy disk image"
    invoke_command "umount $mntdir" "unmounting disk image"
    rm -rf "$mntdir"
}

make_driver_disk_isotar()
{
    local type="$1"
    local image_name="$2"
    local source_dir="$3"
    local file
    case $type in
        iso)
            invoke_command "mkisofs -v -r -J -pad -V $module -o $image_name ." "mkisofs" background
            ;;
        tar)
            invoke_command "tar cvf $image_name ." "tar" background
            ;;
    esac
}

make_driver_disk_media()
{
    echo "Copying files $2"

    case $media in
        floppy*)
            make_driver_disk_floppy "$1" "$2"
            ;;
        iso*)
            make_driver_disk_isotar "iso" "$1" "$2"
            ;;
        tar*)
            make_driver_disk_isotar "tar" "$1" "$2"
            ;;
    esac
}

driver_disk_suffix()
{
    case $media in
    floppy*)
        echo "img"
        ;;
    iso*)
        echo "iso"
        ;;
    tar*)
        echo "tar"
        ;;
    esac
}

make_driver_disk()
{
    # Check that the right arguments were passed
    if ! [[ $module && $module_version && $distro && $kernelver ]]; then
        die 1 $"Invalid number of parameters passed." \
        $"Usage: mkdriverdisk <module>/<module-version> -d <distro> -k <kernelver> [--media floppy|iso|tar]"
    fi

    # Default to floppy media
    [[ $media ]] || media="floppy"
    if ! media_valid; then
        die 1 $"Media $media is invalid." \
            $"Usage: mkdriverdisk <module>/<module-version> -d <distro> -k <kernelver> [--media floppy|iso|tar]"
    fi

    # Check that source symlink works
    check_module_exists

    # Confirm that distro is supported
    case $distro in
        redhat3 | suse | UnitedLinux | ubuntu)
            ;;
        *)
            die 3 $"Invalid distro argument. Currently, the distros supported are: redhat3, suse, UnitedLinux, ubuntu."
            ;;
    esac

    # Read the conf file
    read_conf_or_die "$kernelver" "$arch"

    case $distro in
        redhat*)
            make_redhat3_driver_disk
            ;;
        ubuntu)
            make_ubuntu_driver_disk
            ;;
        *)
            make_suse_driver_disk
            ;;
    esac
}

find_external_dependencies()
{
    local mod count i
    local -a deps

    # Find all module dependencies
    for ((count=0; count < ${#dest_module_name[@]}; count++)); do
        for ((i=0; i < ${#kernelver[@]}; i++)); do
            set_module_suffix "${kernelver[$i]}"
            mod="$dkms_tree/$module/$module_version/${kernelver[$i]}/${arch[$i]}/module/${dest_module_name[$count]}$module_suffix"
            deps=(${deps[@]} $(modinfo "$mod" | sed -n 's/,/ /g; s/^depends: *//p'))
        done
    done

    # Prune internally satisfied dependencies

    for ((i=0; i < ${#deps[@]}; i++)); do
        for mod in ${dest_module_name[@]}; do
            [[ ${deps[i]} = $mod ]] && deps[i]=
        done
    done

    for dep in "${deps[@]}"; do
        echo $dep
    done | sort -u
}

make_suse_driver_disk()
{
    [[ $release ]] || die 3 \
        $"Invalid number of parameters passed for suse/UnitedLinux driver disk." \
        $"Usage: mkdriverdisk <module>/<module-version> -d <distro> -k <kernelver> -r <release-number>"

    local driver_disk_dir=$(mktemp_or_die -d $tmp_location/dkms.XXXXXX)
    local suffix="$(driver_disk_suffix)"
    local image_dir="$dkms_tree/$module/$module_version/driver_disk"
    local image_name="$module-$module_version-$distro-$release-dd.$suffix"

    echo $"Creating driver disk:"

    local deps="$(find_external_dependencies)"

    local offset=0
    # reserve a place for dependencies
    [[ ${deps[@]} ]] && offset=1

    local count
    for ((count=0; count < ${#dest_module_name[@]}; count++)); do
    local i
    local topdir=$(printf "%02d" $(($count+1+offset)))
    for ((i=0; i < ${#kernelver[@]}; i++)); do
        set_module_suffix "${kernelver[$i]}"
        local srcdir=$dkms_tree/$module/$module_version/${kernelver[$i]}/${arch[$i]}/module
        local srcpath=$(compressed_or_uncompressed "$srcdir" "${dest_module_name[$count]}")
        if ! [[ -n "$srcpath" ]]; then
            rm -rf $temp_dir_name
            die 5 \
                $"Cannot find module ${dest_module_name[$count]}$module_suffix for kernel ${kernelver[$i]} (${arch[$i]})." \
                $"Module/version must be in built state before making a driver disk."
        fi
        # FIXME: add check for KMP binary RPMs to include in the driver disk
        suse_arch=${arch[$i]}
        case $suse_arch in
            i?86)
                suse_arch=i386
                ;;
        esac

        echo "Marking ${kernelver[$i]}/${arch[$i]}/modules/${dest_module_name[$count]}$module_suffix..."
        mkdir -p "$driver_disk_dir/$topdir/$suse_arch-$release/install/lib/modules/${kernelver[$i]}${dest_module_location[$count]}"
        cp "$srcpath" "$driver_disk_dir/$topdir/$suse_arch-$release/install/lib/modules/${kernelver[$i]}${dest_module_location[$count]}/"

        case ${kernelver[$i]} in
        *-default)
            mkdir -p "$driver_disk_dir/$topdir/$suse_arch-$release/modules/"
            cp "$srcpath" "$driver_disk_dir/$topdir/$suse_arch-$release/modules/"
            ;;
        esac

        # Create directory for dependency information
        [[ ${deps[@]} ]] && mkdir -p "$driver_disk_dir/01/linux/$distro/$suse_arch-$release/modules"

    done

    # ---
    for arch_release in $(find $driver_disk_dir/$topdir -maxdepth 1 -mindepth 1 -type d | sed "s#$driver_disk_dir\/$topdir\/##"); do
        cd "$driver_disk_dir/$topdir/$arch_release/install/"
        invoke_command "tar cvzf update.tar.gz lib/" "making update.tar.gz for $arch_release" background
        cd - >/dev/null

        mkdir -p "$driver_disk_dir/$topdir/linux/$distro/$arch_release/install"
        mkdir -p "$driver_disk_dir/$topdir/linux/$distro/$arch_release/modules"

        echo $"  copying update.tar.gz for $arch_release to disk image..."
        cp -f "$driver_disk_dir/$topdir/$arch_release/install/update.tar.gz" "$driver_disk_dir/$topdir/linux/$distro/$arch_release/install/"

        postkernels=
        archtest=${arch_release/-*}
        for ((i=0; i<${#kernelver[@]}; i++)); do
            [[ ${arch[$i]} = ${archtest} ]] && postkernels="${postkernels} ${kernelver[$i]}"
        done

        if [[ ${postkernels} ]]; then
            dstfile="$driver_disk_dir/$topdir/linux/$distro/$arch_release/install/update.post"
            echo $"  creating update.post for $arch_release..."
            (cat << EOF
#!/bin/sh

kernlist="${postkernels}"

for kernel in \${kernlist}; do
    if [ -e /boot/System.map-\${kernel} ]; then
    depmod -a -F /boot/System.map-\${kernel} \${kernel}
    fi
done

EOF
            ) > ${dstfile}
            chmod a+x ${dstfile}
            fi

            if [[ -d $driver_disk_dir/$topdir/$arch_release/modules/ ]]; then
                echo $"  copying kernel modules for installation kernel to disk image..."
                cp -f $driver_disk_dir/$topdir/$arch_release/modules/* $driver_disk_dir/$topdir/linux/$distro/$arch_release/modules/ 2>/dev/null
            else
                warn $"No kernel modules found for -default kernel."
            fi

            rm -fr "$driver_disk_dir/$topdir/$arch_release"
        done
    done

    local dir
    if [[ ${deps[@]} ]]; then
        for dir in "$driver_disk_dir/01/linux/$distro/"*"/modules"; do
            for dep in "${deps[@]}"; do
                echo $dep >> "$dir/module.order"
            done
        done
    fi

    # FIXME: add suse-equivalent rpms/ directory, copy in KMP RPMs, run createrepo --pretty

    mkdir -p "$image_dir"
    rm -f "$image_dir/$image_name"
    cd "$driver_disk_dir"
    make_driver_disk_media "$image_dir/$image_name" "$driver_disk_dir"
    cd - >/dev/null
    rm -rf "$driver_disk_dir"

    echo $""
    echo $"Disk image location: $dkms_tree/$module/$module_version/driver_disk/$image_name"
}

make_ubuntu_driver_disk()
{
    local suffix="$(driver_disk_suffix)"
    local image_dir="$dkms_tree/$module/$module_version/driver_disk"
    local image_name="$module-$module_version-$distro-dd.$suffix"

    local tempdir=$(mktemp_or_die -d $tmp_location/dkms.XXXXXX)

    # Check that the dh_make command is present
    if ! which dpkg-deb >/dev/null 2>&1 ; then
        die 1 $"dpkg-deb not present." \
            $"Install the dpkg-dev package."
    fi

    local i
    for ((i=0; i < ${#kernelver[@]}; i++)); do
        set_module_suffix "${kernelver[$i]}"
        # Driver disks only recognize i386 as package arch
        local karch=${arch[$i]/i?86/i386}
        local kvers=${kernelver[$i]/-/_}; kvers=${kvers%%_*}
        # ubuntu-drivers/<kver>/*_<debarch>.deb
        local dd_prefix="ubuntu-drivers/$kvers"
        local dd_suffix="_${karch}.deb"
        maybe_build_module "$module" "$module_version" "${kernelver[$i]}" "${arch[$i]}" || {
            rm -rf "$tempdir"
            die 5 $"Unable to build $module/$module_version for Ubuntu driver disk."
        }
        mkdir -p "$tempdir/$dd_prefix"
        local deb_dir="$tempdir/$dd_prefix/debian"
        local deb_lib_dir="$deb_dir/lib/modules/${kernelver[$i]}/updates/dkms"
        mkdir -p "$deb_lib_dir"
        cp "$dkms_tree/$module/$module_version/${kernelver[$i]}/${arch[$i]}/module/"*"$module_uncompressed_suffix"* "$deb_lib_dir"
        pushd "$deb_dir" > /dev/null 2>&1
        mkdir DEBIAN
        cat > DEBIAN/control <<EOF
Package: ${module}-modules-${kernelver[$i]}
Version: ${module_version}-1
Section: misc
Priority: optional
Architecture: $karch
Depends:
Maintainer: DKMS <dkms-devel@dell.com>
Description: DKMS packaged binary driver update
 DKMS automagically generated debian package for
 driver update disks, used with Ubuntu installation
 programs (such as Ubiquity).
EOF

       # Generate the DEBIAN/preinst file.
       # This is tricky as we need some parts evaluated now
       # and some parts evaluated at runtime
cat >DEBIAN/preinst <<EOF
#!/bin/bash
[[ \$(uname -r) = ${kernelver[$i]} ]] || exit 1
exit 0
EOF
       chmod 0775 DEBIAN/preinst
       cd "$tempdir/$dd_prefix"
       dpkg-deb --build debian
       mv debian.deb "${module}_${module_version}-${kernelver[$i]}${dd_suffix}"
       rm -rf debian
       popd > /dev/null 2>&1
   done

   echo "Copying source..."
   mkdir -p "$tempdir/ubuntu"
   cp -ar "$source_tree/$module-$module_version" "$tempdir/ubuntu/"

   mkdir -p "$image_dir"
   rm -f "$image_dir/$image_name"
   cd "$tempdir"
   make_driver_disk_media "$image_dir/$image_name" "$tempdir"
   cd - >/dev/null
   rm -rf "$tempdir"
   echo $""
   echo $"Disk image location: $dkms_tree/$module/$module_version/driver_disk/$image_name"
}

make_tarball()
{
    make_common_test "mktarball"

    # Check for dkms_dbversion
    if ! [[ -e $dkms_tree/dkms_dbversion ]]; then
        echo $"" >&2
        echo $"Could not find the file $dkms_tree/dkms_dbversion." >&2
        echo $"Creating w/ default contents." >&2
        echo "2.0.0" > $dkms_tree/dkms_dbversion
    fi

    # Read the conf file
    read_conf_or_die "$kernelver" "$arch"

    temp_dir_name=$(mktemp_or_die -d $tmp_location/dkms.XXXXXX)
    mkdir -p $temp_dir_name/dkms_main_tree

    if [[ $source_only ]]; then
    kernel_version_list="source-only"
    else
    local i
    for ((i=0; i<${#kernelver[@]}; i++)); do
        if ! [[ -d $dkms_tree/$module/$module_version/${kernelver[$i]}/${arch[$i]} ]]; then
            rm -rf "$temp_dir_name" 2>/dev/null
            die 6  $"No modules built for ${kernelver[$i]} (${arch[$i]})." \
                $"Modules must already be in the built state before using mktarball."
        fi

        set_module_suffix "${kernelver[$i]}"

        echo "Marking modules for ${kernelver[$i]} (${arch[$i]}) for archiving..."
        if [[ ! $kernel_version_list ]]; then
            kernel_version_list="kernel${kernelver[$i]}-${arch[$i]}"
        else
            kernel_version_list="${kernel_version_list}-kernel${kernelver[$i]}-${arch[$i]}"
        fi
        mkdir -p "$temp_dir_name/dkms_main_tree/${kernelver[$i]}/${arch[$i]}"
        cp -rf "$dkms_tree/$module/$module_version/${kernelver[$i]}/${arch[$i]}" "$temp_dir_name/dkms_main_tree/${kernelver[$i]}"
    done
    fi

    # Store the dkms_dbversion in the tarball
    cp -f "$dkms_tree/dkms_dbversion" "$temp_dir_name/dkms_main_tree/"

    # Copy the source_tree or make special binaries-only structure
    if [[ $binaries_only ]]; then
        echo $""
        echo $"Creating tarball structure to specifically accomodate binaries."
        mkdir $temp_dir_name/dkms_binaries_only
        echo "$module" > $temp_dir_name/dkms_binaries_only/PACKAGE_NAME
        echo "$module_version" > $temp_dir_name/dkms_binaries_only/PACKAGE_VERSION
        [[ ! $conf ]] && conf="$dkms_tree/$module/$module_version/source/dkms.conf"
        cp -f $conf $temp_dir_name/dkms_binaries_only/ 2>/dev/null
    else
        echo $""
        echo $"Marking $dkms_tree/$module/$module_version/source for archiving..."
        mkdir -p $temp_dir_name/dkms_source_tree
        cp -rf $dkms_tree/$module/$module_version/source/* $temp_dir_name/dkms_source_tree
    fi

    if (( $(echo $kernel_version_list | wc -m | awk {'print $1'}) > 200 )); then
        kernel_version_list="manykernels"
    fi

    local tarball_name="$module-$module_version-$kernel_version_list.dkms.tar.gz"
    local tarball_dest="$dkms_tree/$module/$module_version/tarball/"

    # Die if we will not be able to create the tarball due to permissions.
    if [[ $archive_location ]]; then
        tarball_name="${archive_location##*/}"
        if [[ ${archive_location%/*} != $archive_location && \
            -d ${archive_location%/*} && -w ${archive_location%/*} ]]; then
            tarball_dest="${archive_location%/*}"
        elif [[ ${archive_location%/*} != $archive_location ]] && ! mkdir -p $tarball_dest; then
            die 9 $"Will not be able to create $archive_location due to a permissions problem."
        fi
    fi
    if [ ! -d $tarball_dest ]; then
        mkdir -p "$dkms_tree/$module/$module_version/tarball/"
    fi

    echo $""
    echo $"Tarball location: $tarball_dest/$tarball_name"

    local tarball_ext=${tarball_name##*.}
    [[ $tarball_ext = tar ]] || tarball_name=${tarball_name%.$tarball_ext}

    # Make the tarball
    cd $temp_dir_name
    if tar -cf $temp_dir_name/$tarball_name ./* 2>/dev/null; then
        cd - >/dev/null
        echo $""
        mv -f "$temp_dir_name/$tarball_name" "$tarball_dest/$tarball_name"
        rm -rf $temp_dir_name
    else
        cd - >/dev/null
        rm -rf $temp_dir_name
        die 6 $"Failed to make tarball."
    fi
    case $tarball_ext in
        gz)
            gzip -f -9 "$tarball_dest/$tarball_name"
            ;;
        bz2)
            bzip2 -f -9 "$tarball_dest/$tarball_name"
            ;;
        xz)
            xz -f -9 "$tarball_dest/$tarball_name"
            ;;
    esac
}

# A tiny helper function to make sure dkms.conf describes a valid package.
get_pkginfo_from_conf() {
    [[ -f $1 && $1 = *dkms.conf ]] || return
    read_conf_or_die "$kernelver" "$arch" "$1"
    [[ $PACKAGE_NAME && $PACKAGE_VERSION ]]
}

# Unpack a DKMS tarball from a few different supported formats.
# We expect $archive_location to have been passed either as a raw argument or
# with --archive.
load_tarball()
{
    # Error out if $archive_location does not exist
    if [[ ! -e $archive_location ]]; then
        die 2 $"$archive_location does not exist."
    fi

    # If it is an .rpm file. install it with rpm, run an autoinstall, and then exit.
    if [[ $archive_location = *.rpm ]]; then
       if rpm -Uvh "$archive_location"; then
           autoinstall
           exit $?
       else
           die 9 $"Unable to install $archive_location using rpm." \
               $"Check to ensure that your system can install .rpm files."
       fi
    fi

    # Figure out what kind of archive it is (tar.gz, tar, tar.bz, tar.xz, etc)
    # Note that this does not depend on the extensions being correct.
    local tar_options=""
    for xpand in gzip bzip xz; do
        $xpand -t $archive_location 2>/dev/null || continue
        case $xpand in
            gzip)
                tar_options=z
                ;;
            bzip2)
                tar_options=j
                ;;
            xz)
                tar_options=J
                ;;
        esac
        break
    done

    # Untar it into $tmp_location
    local temp_dir_name=$(mktemp_or_die -d $tmp_location/dkms.XXXXXX)
    trap 'rm -rf $temp_dir_name' EXIT
    tar -${tar_options}xf $archive_location -C $temp_dir_name

    if [[ ! $temp_dir_name/dkms_main_tree ]]; then
    # Tarball was not generated from mktarball.
    # Just find the dkms.conf file and load the source.
    conf=$(find $temp_dir_name/ -name dkms.conf 2>/dev/null | head -n 1)
    if [[ ! $conf ]]; then
        rm -rf $temp_dir_name
        die 3 $"Tarball does not appear to be a correctly formed DKMS archive. No dkms.conf found within it."
    fi
    add_source_tree "${conf%dkms.conf}"
    return
    fi

    # Check that dkms_dbversion is not a future version
    # As far as I can tell, the only reason we bother with this is for detecting
    # whether we have arch support or not, which we can also determine by examining
    # the structure of the tarball.
    db_from_tarball=$(cat $temp_dir_name/dkms_main_tree/dkms_dbversion 2>/dev/null)
    db_from_dkms=$(cat $dkms_tree/dkms_dbversion 2>/dev/null)
    if [[ $db_from_tarball && $db_from_dkms && $(VER "$db_from_tarball") > $(VER "$db_from_dkms") ]]; then
        die 9 \
            $"The tarball you are trying to load indicates it is database version $db_from_tarball."\
            $"This version of DKMS only supports $db_from_dkms or lower."
    fi

    # Make sure its a sane tarball. Sane ones will have one of the two
    # directories we test for.
    for loc in dkms_source_tree dkms_binaries_only ''; do
    if [[ ! $loc ]]; then
        die 7 $"No valid dkms.conf in dkms_source_tree or dkms_binaries_only." \
            $"$archive_location is not a valid DKMS tarball."
    fi
    local conf="$temp_dir_name/$loc/dkms.conf"
    [[ -f $conf ]] || continue
    if ! get_pkginfo_from_conf "$conf"; then
        echo >&2
        echo $"Malformed dkms.conf, refusing to load." >&2
        continue
    fi
    if is_module_added "$PACKAGE_NAME" "$PACKAGE_VERSION" && \
        [[ ! $force ]]; then
        die 8  $"$PACKAGE_NAME-$PACKAGE_VERSION is already added!" \
        $"Aborting."
    fi
    module="$PACKAGE_NAME"; module_version="$PACKAGE_VERSION"
    echo $""
    echo $"Loading tarball for $module-$module_version"
    case $loc in
        dkms_source_tree)
            add_source_tree "$temp_dir_name/dkms_source_tree"
            ;;
        dkms_binaries_only)
            #if there is a source tree on the system already, don't build a binaries stub
            if [[ ! -d $source_tree/$module-$module_version ]]; then
                echo $"Creating $dkms_tree/$module/$module_version/source"
                mkdir -p "$dkms_tree/$module/$module_version/source"
                echo $"Copying dkms.conf to $dkms_tree/$module/$module_version/source..."
                cp -rf "$temp_dir_name/dkms_binaries_only/dkms.conf" "$dkms_tree/$module/$module_version/source"
            fi
            ;;
        *)
            die 8 $"$FUNCNAME:$LINENO: Cannot happen." \
                $"Report this error to dkms-devel@dell.com";;
    esac
    break
    done

    # At this point, the source has been copied to the appropriate location
    # and registered with dkms, or a binary-only config has been noted.
    # Now, add any included precompiled modules.

    # Is tarball from before DKMS 2.0 (prior to arch support)
    if [[ ! -e $temp_dir_name/dkms_main_tree/dkms_dbversion ]]; then
        [[ $loc = dkms_binaries_only ]] && rm -rf "$dkms_tree/$module/$module_version/source"
        die 10 $"This tarball was created with dkms < 2.0 and contains no arch info."\
               $"DKMS is refusing to install precompiled modules."
    fi

    # Load precompiled modules.
    for directory in "$temp_dir_name/dkms_main_tree"/*/*; do
        [[ -d $directory ]] || continue
        kernel_arch_to_load=${directory/*dkms_main_tree\/}
        dkms_dir_location="$dkms_tree/$module/$module_version/$kernel_arch_to_load"
        if [[ -d $dkms_dir_location && ! $force ]]; then
            warn $"$dkms_dir_location already exists. Skipping..."
        else
            echo $"Loading $dkms_dir_location..."
            rm -rf $dkms_dir_location
            mkdir -p $dkms_dir_location
            cp -rf $directory/* $dkms_dir_location/
        fi
    done

    [[ $loc != dkms_binaries_only ]] || [[ -d $source_tree/$module-$module_version ]]
}

run_match()
{
    set_kernel_source_dir "$kernelver"

    # Error if $template_kernel is unset
    if [[ ! $template_kernel ]]; then
        die 1 $"Invalid number of parameters passed." \
            $"Usage: match --templatekernel=<kernel-version> -k <kernel-version>" \
            $"   or: match --templatekernel=<kernel-version> -k <kernel-version> <module>"
    fi

    # Error out if $template_kernel = $kernel_version
    if [[ $template_kernel = $kernelver ]]; then
        die 2 $"The templatekernel and the specified kernel version are the same."
    fi

    # Read in the status of template_kernel
    local template_kernel_status=$(do_status '' '' $template_kernel $arch | grep ": installed")

    # If $module is set, grep the status only for that module
    if [[ $module ]]; then
        # Make sure that its installed in the first place
        if ! [[ -d $dkms_tree/$module/ ]]; then
            die 3 $"The module: $module is not located in the DKMS tree."
        fi
        template_kernel_status=$(echo "$template_kernel_status" | grep "^$module,")
    fi

    echo $""
    echo $"Matching modules in kernel: $kernelver ($arch)"
    echo $"to the configuration of kernel: $template_kernel ($arch)"

    # Prepare the kernel just once but only if there is actual work to do
    if [[ ! $template_kernel_status ]]; then
        echo $""
        echo $"There is nothing to be done for this match."
    else
    prepare_kernel "$kernelver" "$arch"

    # Iterate over the kernel_status and match kernel to the template_kernel
    while read template_line; do
        template_module=`echo "$template_line" | awk {'print $1'} | sed 's/,$//'`
        template_version=`echo "$template_line" | awk {'print $2'} | sed 's/,$//'`

        # Print out a match header
        echo $"Module:  $template_module"
        echo $"Version: $template_version"

        # Figure out what to do from here
        if show_status "$template_module" "$template_version" "$kernelver" "$arch" 2>/dev/null | grep -q ": installed"; then
            echo $""
            echo $"This module/version combo is already installed. Nothing to be done."
        elif show_status "$template_module" "$template_version" "$kernelver" "$arch" 2>/dev/null | grep -q ": built"; then
            echo $""
            echo $"This module/version combo is built. Installing it:"
            module="$template_module"
            module_version="$template_version"
            install_module
        else
        echo $""
        echo $"Building & Installing this module/version:"
        module="$template_module"
        module_version="$template_version"
        build_module
        install_module
        fi
    done < <(echo "$template_kernel_status")

    # Clean up the kernel tree
    if [[ ! ( $(VER $kernelver) < $(VER 2.6.6) ) && -d "$kernel_source_dir" && ! -h "$kernel_source_dir" && -z "$ksourcedir_fromcli" ]]; then
        echo $"Kernel cleanup unnecessary for this kernel. Skipping..."
    elif [[ ! $no_clean_kernel ]]; then
        cd "$kernel_source_dir"
        [[ $kerneldoth_contents ]] || invoke_command "make mrproper" "cleaning kernel tree (make mrproper)" background
        [[ $config_contents ]] && echo "$config_contents" > .config
        [[ $kerneldoth_contents ]] && echo "$kerneldoth_contents" > /boot/kernel.h
        cd - >/dev/null
    fi
    fi
}

make_rpm()
{
    make_common_test "mkrpm"

    # Check that the rpmbuild command is present
    if ! which rpmbuild >/dev/null 2>&1 ; then
        die 1 $"rpmbuild not present." \
            $"Install the rpm-build package."
    fi

    # Read the conf file
    read_conf_or_die "$kernelver" "$arch"

    local rpm_basedir="$dkms_tree/$module/$module_version/rpm"

    echo $""
    local sp
    for sp in "$dkms_tree/$module/$module_version/source/$module-dkms-mkrpm.spec" "/etc/dkms/template-dkms-mkrpm.spec"; do
        [[ -e $sp ]] || continue
        SPECFILE="$sp"
        break
    done
    if [[ ! $SPECFILE ]]; then
        die 5 $"Cannot find $sp which is needed by DKMS in order use mkrpm."
    fi

    # Run a dkms mktarball for use in the rpm
    local mktarball_line
    if [[ ! $source_only || $binaries_only ]]; then
        mktarball_line="--binaries-only"
        local i
        echo $""
        for ((i=0; i<${#kernelver[@]}; i++)); do
            if ! [[ -d $dkms_tree/$module/$module_version/${kernelver[$i]}/${arch[$i]} ]]; then
                die 5 $"You do not seem to have $module $module_version built for ${kernelver[$i]} (${arch[$i]})."\
                    $"All modules must be in the built state before you can use mkrpm."
            fi
            echo $"Marking ${kernelver[$i]} (${arch[$i]}) for RPM..."
            mktarball_line="-k ${kernelver[$i]} -a ${arch[$i]} $mktarball_line"
        done
    else
        mktarball_line="none"
    fi

    local temp_dir_name=$(mktemp_or_die -d $tmp_location/dkms.XXXXXX)
    trap 'rm -rf $temp_dir_name' EXIT HUP TERM
    mkdir -p ${temp_dir_name}/{BUILD,RPMS,SRPMS,SPECS,SOURCES}
    cp ${SPECFILE} ${temp_dir_name}/SPECS/dkms_mkrpm.spec

    # If using legacy mode, install common postinst
    if ((legacy_postinst != 0)); then
        invoke_command "cp '$PREFIX/usr/lib/dkms/common.postinst' '${temp_dir_name}/SOURCES'" "copying legacy postinstall template"
    fi

    # Copy in the source tree
    if [[ ! $binaries_only ]]; then
        invoke_command "cp -Lpr '$dkms_tree/$module/$module_version/source' '${temp_dir_name}/SOURCES/$module-$module_version'" "Copying source tree"
    fi

    if invoke_command "LC_ALL=C rpmbuild --define \"_topdir ${temp_dir_name}\" --define \"version $module_version\" --define \"module_name $module\" --define \"kernel_versions ${kernelver[*]}\" --define \"mktarball_line $mktarball_line\" --define \"__find_provides  /usr/lib/dkms/find-provides\" --define \"_use_internal_dependency_generator 0\" -ba ${temp_dir_name}/SPECS/dkms_mkrpm.spec > ${temp_dir_name}/rpmbuild.log 2>&1" "rpmbuild"; then
        mkdir -p ${rpm_basedir}
        cp -a ${temp_dir_name}/SRPMS/* ${temp_dir_name}/RPMS/*/* ${rpm_basedir}/
        echo $""
        cat ${temp_dir_name}/rpmbuild.log | grep ^Wrote | sed -e "s:${temp_dir_name}/:${rpm_basedir}/:" -e 's:SRPMS/::' -e 's:RPMS/.*/::'
    else
        cat ${temp_dir_name}/rpmbuild.log >&2
        die 7 $"There was a problem creating your rpm."
    fi
    rm -rf $temp_dir_name
    trap > /dev/null 2>&1
}

preproc_file()
{
    local date_str="$(date -R)"
    echo "modifying $1..."
    sed -e "s/DEBIAN_PACKAGE/$debian_package/g" \
	-e "s/DEBIAN_BUILD_ARCH/$debian_build_arch/g" \
	-e "s/KERNEL_VERSION/$kernelver/g" \
        -e "s/MODULE_NAME/$module/g" \
        -e "s/MODULE_VERSION/$module_version/g" \
        -e "s/DATE_STAMP/$date_str/" "$1" > "$1.dkms-pp"
    mv "$1.dkms-pp" "$1"
}

# Install a package on a debian system.
debian_install()
{
    local getroot  tmpfile i
    local -a packages=("$@")
    for ((i=0; i < ${#packages[@]}; i++)); do
        dpkg-query -s "${packages[$i]}"| egrep -q '^Status:.* installed$' || continue
        unset package[$i]
    done
    # if they are already installed, we are OK.
    [[ ${package[@]} ]] || return
    if [[ $(id -u) != 0 ]]; then
        # figure out how to get root
        for getroot in su-to-root gksudo kdesu sudo; do
            which $getroot >/dev/null 2>&1 || continue
            case $getroot in
                su-to-root)
                    getroot="$getroot -c"
                    ;;
                gksudo)
                    [[ $DISPLAY ]] || continue
                    getroot="$getroot --description 'DKMS Debian package builder' "
                    ;;
                kdesu)
                    [[ $DISPLAY ]] || continue
                    ;;
            esac
            break
        done
    fi
    if [[ -x /usr/sbin/synaptic && $DISPLAY ]] && tmpfile=$(mktemp_or_die); then
        # Pretty GUI install.
        trap 'rm -f "$tmpfile"' EXIT
        for ((i=0; i=${#packages[@]}; i++)); do
            [[ ${packages[$i]} ]] && echo "install ${packages[$i]}" >>$tmpfile
        done
        $getroot "sh -c '/usr/sbin/synaptic --set-selections --non-interactive --hide-main-window < $tmpfile'"
    else
        $getroot apt-get -y install "${packages[@]}"
    fi
    if (( $? != 0)); then
        die 4 $"Missing ${packages[@]} and unable to install. Please ask an admin to install for you."
    fi
}

make_debian()
{
    create_type="$1"

    create_temporary_trees
    trap "delete_temporary_trees" EXIT HUP TERM

    make_common_test "mk${create_type}"

    debian_package=${module//_/-}
    if [[ $source_only ]]; then
         debian_build_arch='all'
    else
         debian_build_arch=$(dpkg-architecture -qDEB_BUILD_ARCH)
    fi

    # Read the conf file
    read_conf_or_die "$kernelver" "$arch"
    debian_install fakeroot dpkg-dev debhelper

    # Skeleton to load templates from
    local system_mk="$dkms_tree/$module/$module_version/source/$module-dkms-mk${create_type}"
    local local_mk="/etc/dkms/template-dkms-mk${create_type}"
    if [[ -e ${system_mk} ]]; then
        echo $"Using ${system_mk}"
        DEBDIR=${system_mk}
    elif [[ -e ${local_mk} ]]; then
        echo $"Using ${local_mk}"
        DEBDIR=${local_mk}
    else
        die 5 $"Cannot find ${local_mk} which is needed by DKMS in order to use mk${create_type}."
    fi

    # Prepare build directory and copy template
    local temp_dir=$(mktemp_or_die -d $tmp_location/dkms.XXXXXX)
    trap "rm -rf $temp_dir; delete_temporary_trees" EXIT HUP TERM
    local temp_dir_debian="$temp_dir/$debian_package-dkms-$module_version"
    invoke_command "cp -ar '$DEBDIR/' '$temp_dir_debian'" "copying template"
    pushd "$temp_dir_debian" > /dev/null 2>&1
    for file in debian/*; do
        preproc_file "$file"
        chmod 755 "$file"
    done
    popd > /dev/null 2>&1

    # If using legacy mode, install common postinst
    if ((legacy_postinst != 0)); then
        invoke_command "cp '$PREFIX/usr/lib/dkms/common.postinst' '$temp_dir_debian'" "copying legacy postinstall template"
    fi

    # Calculate destination directory
    deb_basedir=$dkms_tree/$module/$module_version/${create_type}
    mkdir -p ${deb_basedir} >/dev/null 2>&1

    # Create deb
    pushd "$temp_dir_debian" > /dev/null 2>&1
    case "$create_type" in
    dsc)
        invoke_command "cp -Lpr '$dkms_tree/$module/$module_version/source' '$temp_dir_debian/$module-$module_version'" "Copying source tree"
        invoke_command "dpkg-buildpackage -S -us -uc 1>/dev/null" "Building source package" || \
            die 7 $"There was a problem creating your ${create_type}."
        invoke_command "mv '$temp_dir/${debian_package}-dkms_${module_version}_source.changes' '$temp_dir/${debian_package}-dkms_${module_version}.dsc' '$temp_dir/${debian_package}-dkms_${module_version}.tar.gz' '$deb_basedir'" "Moving built files to $deb_basedir"
        ;;
    deb)
        invoke_command "cp -Lpr '$dkms_tree/$module/$module_version/source' '$temp_dir_debian/$module-$module_version'" "Copying source tree"
        invoke_command "dpkg-buildpackage -rfakeroot -d -b -us -uc 1>/dev/null" "Building binary package" || \
            die 7 $"There was a problem creating your ${create_type}."
        invoke_command "mv '$temp_dir/${debian_package}-dkms_${module_version}_${debian_build_arch}.deb' '$deb_basedir'" "Moving built files to $deb_basedir"
	;;
    bmdeb)
        local archive_location="$dkms_tree/$module/$module_version/tarball/$module-$module_version.dkms.tar.gz"
        # Force binaries_only
        binaries_only="binaries-only"
        invoke_command "make_tarball" "Gathering binaries"
        if [[ -f $archive_location ]]; then
            invoke_command "cp '$archive_location' '$temp_dir_debian'" "Copying DKMS tarball into DKMS tree"
        else
            die 12 $"Unable to find created tarball."
        fi
        export KVER="$kernelver"
        export KARCH="$arch"
        invoke_command "dpkg-buildpackage -rfakeroot -d -b -us -uc 1>/dev/null" "Building binary package" || \
        die 7 $"There was a problem creating your ${create_type}."
        invoke_command "mv '$temp_dir/${debian_package}-modules-${kernelver}_${module_version}_${debian_build_arch}.deb' '$deb_basedir'" "Moving built files to $deb_basedir"
        ;;
    esac
    popd > /dev/null 2>&1

    if in_temporary_trees; then
        echo "Copying built files to "`pwd`"/.." >&2
        cp "${deb_basedir}/"* ..
    fi

    # Cleanup
    invoke_command "rm $temp_dir -fr" "Cleaning up temporary files"
    delete_temporary_trees || \
        die 7 $"There was a problem cleaning up temporary files."
}

make_common_test()
{
    local create_type=$1
    # Error if $module_version is set but $module is not
    check_module_args $create_type

    # Check that source symlink works
    check_module_exists

    # Make sure that its installed in the first place
    [[ -d $dkms_tree/$module/$module_version ]] ||
        die 3 $"Module $module-$module_version is not located in the DKMS tree."
}

make_kmp_srpm()
{
    local temp_dir_name=$(mktemp_or_die -d $tmp_location/dkms.XXXXXX)
    trap 'rm -rf $temp_dir_name' EXIT HUP TERM
    mkdir -p $temp_dir_name/{BUILD,RPMS,SRPMS,SPECS,SOURCES}
    pushd "$dkms_tree/$module/$module_version" > /dev/null 2>&1
    # Want to change name of the top-level of the tarball from build to $module-$module_version
    cp -lr build ${module}-${module_version}
    tar cvjf $temp_dir_name/SOURCES/${module}-${module_version}.tar.bz2 ${module}-${module_version} > /dev/null 2>&1
    rm -rf ${module}-${module_version}
    popd > /dev/null 2>&1
    pushd "$temp_dir_name" > /dev/null 2>&1
    invoke_command "rpmbuild --define \"_topdir ${temp_dir_name}\" --target=$arch -bs ${SPECFILE} > ${temp_dir_name}/rpmbuild.log 2>&1" "rpmbuild"
    grep ^Wrote $temp_dir_name/rpmbuild.log > /dev/null 2>&1
    local RC="$?"
    if ((RC == 0)); then
        local kmp_basedir="$dkms_tree/$module/$module_version/rpm"
        mkdir -p $kmp_basedir
        RPMS=$(LANG=C cp -va ${temp_dir_name}/SRPMS/* $kmp_basedir | awk '{print $NF}')
    else
        echo $"rpmbuild error log:"
        cat $temp_dir_name/rpmbuild.log
    fi
    popd > /dev/null 2>&1
    rm -rf $temp_dir_name
    trap > /dev/null 2>&1
    return ${RC}
}

report_build_problem()
{
    # If apport is on the system, files a build problem
    if [ -x /usr/share/apport/apport ] && which python3 >/dev/null; then
        python3 /usr/share/apport/package-hooks/dkms_packages.py -m $module -v $module_version -k ${kernelver[0]}
    fi
    die "$@"
}

# Little helper function for reading args from the commandline.
# it automatically handles -a b and -a=b variants, and returns 1 if
# we need to shift $3.
read_arg() {
    # $1 = arg name
    # $2 = arg value
    # $3 = arg parameter
    local rematch='^[^=]*=(.*)$'
    if [[ $2 =~ $rematch ]]; then
        read "$1" <<< "${BASH_REMATCH[1]}"
    else
        read "$1" <<< "$3"
        # There is no way to shift our callers args, so
        # return 1 to indicate they should do it instead.
        return 1
    fi
}

# A couple of helper functions for parsing out our most common arguments.
# This one allows you to pass -k kernel.version-extra/arch instead of
# -k kernel-version.extra -a arch.
# This makes it harder to pass mismatching numbers of kernel/arch pairs, because
# they are all passed at the same time.
parse_kernelarch(){
    if [[ $1 =~ $mv_re ]]; then
        kernelver[${#kernelver[@]}]="${BASH_REMATCH[1]}"
        arch[${#arch[@]}]="${BASH_REMATCH[2]}"
    else
        kernelver[${#kernelver[@]}]="$1"
    fi
}

# This allows you to pass module and module_version information on the commandline
# in a more convenient form.  Instead of the mostly mandatory and annoying
# -m module -v module_version, you can use either -m module/module_version,
# or just a raw module/module_version with no -m parameter.
# This vastly improves readability and discoverability of
# commands on the commandline.
parse_moduleversion(){
    if [[ $1 =~ $mv_re ]]; then
        module="${BASH_REMATCH[1]}"
        module_version="${BASH_REMATCH[2]}"
    else
        module="$1"
    fi
}

check_root() {
    [[ $(id -u) = 0 ]] && return
    die 1 $"You must be root to use this command."
}

# Add a passed source tree to the default source location.
# We will check the dkms.conf file to make sure it is valid
# beforehand.
add_source_tree() {
    local from=$(readlink -f $1)
    if ! [[ $from && -f $from/dkms.conf ]]; then
        die 9 $"$1 must contain a dkms.conf file!"
    fi
    check_root
    setup_kernels_arches
    if ! get_pkginfo_from_conf "$from/dkms.conf" ; then
        die 10 $"Malformed dkms.conf file. Cannot load source tree."
    fi
    module="$PACKAGE_NAME"
    module_version="$PACKAGE_VERSION"
    if [[ $force && -d $source_tree/$module-$module_version ]]; then
        echo >&2
        echo $"Forcing install of $module-$module_version"
        rm -rf "$source_tree/$module-$module_version"
    fi

    # We are already installed, just return.
    case $from in
        "$source_tree/$module-$module_version")
            return
            ;;
        "$dkms_tree/$module/$version/source")
            return
            ;;
        "$dkms_tree/$module/$version/build")
            return
            ;;
    esac
    mkdir -p "$source_tree/$module-$module_version"
    cp -fr "$from"/* "$source_tree/$module-$module_version"
}

make_kmp()
{
    make_common_test "mkkmp"

    # Read the conf file
    read_conf_or_die "$kernelver" "$arch"

    echo $""
    if [[ $specfile && -e $dkms_tree/$module/$module_version/source/$specfile ]]; then
        echo $"Using $dkms_tree/$module/$module_version/source/$specfile"
        SPECFILE="$dkms_tree/$module/$module_version/source/$specfile"
    elif [[ -e $dkms_tree/$module/$module_version/source/$module-kmp.spec ]]; then
        echo $"Using $dkms_tree/$module/$module_version/source/$module-kmp.spec"
        SPECFILE="$dkms_tree/$module/$module_version/source/$module-kmp.spec"
    else
        die 5 $"Cannot find a suitable spec file which is needed by DKMS in order use mkkmp."\
          $"Please specify --spec=specfile."
    fi

    prepare_build
    make_kmp_srpm
    RC=$?
    clean_build

    if ((RC == 0)); then
        echo $""
        echo $"KMP SRPM location: $RPMS"
    else
        die 7 $"There was a problem creating your KMP source rpm."
    fi
    # FIXME: hand SRPM to mock or build system to build
}

# This code used to be in dkms_autoinstaller.
# Moving it into the main dkms script gets rid of a fair amount of duplicate
# functionality, and makes it much easier to reinstall DKMS kernel modules
# by hand if dkms_autoinstaller is not used.
autoinstall() {
    local status mv mvka m v k a last_v last_m tenative
    local install_count next_depends
    local -a to_install=()
    local -a next_install=()
    local -a installed_modules=()
    local -A build_depends=()

    # Walk through our list of installed and built modules, and create
    # a list of modules that need to be reinstalled.
    # Assuming all versions of same module to be parsed sequentially.
    while read status mvka; do
        IFS='/' read m v k a <<< "$mvka"
        [[ ! $last_m ]] && last_m="$m"
        # autoinstall previous module's latest version after its deps.
        if [[ $last_m != $m ]]; then
            if [[ $tenative ]]; then
                to_install[${#to_install[@]}]="$tenative"
                build_depends["$last_m"]="${BUILD_DEPENDS[@]}"
            fi
            last_m="$m"
            last_v='0'
            tenative=''
        fi
        # If the module is already installed or weak-installed, skip it.
        if _is_module_installed "$m" "$v" "$kernelver" "$arch"; then
            installed_modules[${#installed_modules[@]}]="$m"
            continue
        fi
        if module_status_weak "$m" "$v" "$kernelver" "$arch" >/dev/null; then
            installed_modules[${#installed_modules[@]}]="$m"
            continue
        fi
        # if the module does not want to be autoinstalled, skip it.
        read_conf_or_die "$k" "$a" "$dkms_tree/$m/$v/source/dkms.conf"
        if [[ ! $AUTOINSTALL ]]; then
            continue
        fi
        # otherwise, only autoinstall the latest version we have hanging around.
        if [[ ($(VER $v) > $(VER $last_v)) ]]; then
            last_v="$v"
            tenative="$m/$v"
        fi
    done < <(module_status)

    # We may have exited the loop with $tenative set.  If it is,
    # it contains something that should be updated.
    if [[ $tenative ]]; then
        to_install[${#to_install[@]}]="$tenative"
        build_depends["$m"]="${BUILD_DEPENDS[@]}"
    fi

    [[ $to_install ]] || return 0

    while true; do
        install_count=0
        next_install=( )

        # Step 1: Remove installed modules from all dependency lists.
        for m in ${!build_depends[@]}; do
            next_depends=
            for d in ${build_depends[$m]}; do
                for i in ${installed_modules[@]}; do
                    [[ "$d" = "$i" ]] && continue 2
                done
                next_depends+="$d "
            done
            build_depends[$m]="${next_depends%% }"
        done

        # Step 2: Install modules that have an empty dependency list.
        for mv in "${to_install[@]}"; do
            IFS=/ read m v <<< "$mv"
            if [[ -z "${build_depends[$m]}" ]]; then
                (module="$m" module_version="$v" kernelver="$kernelver" arch="$arch" install_module)
                installed_modules[${#installed_modules[@]}]="$m"
                install_count=$(($install_count +1))
            else
                next_install[${#next_install[@]}]="$mv"
            fi
        done

        wait

        # Step 3: Keep going if at least one module was installed during
        # this iteration.
        [[ "$install_count" -gt 0 ]] || break;

        # Step 4: Remove modules that were installed during Step 2 from
        # the job queue.
        to_install=( "${next_install[@]}" )

    done
    for mv in "${to_install[@]}"; do
        IFS=/ read m v <<< "$mv"
        echo "$m/$v autoinstall failed due to missing dependencies: ${build_depends[$m]}"
    done
}

make_redhat3_driver_disk ()
{
    # Check that the rpmbuild command is present
    if ! which rpmbuild >/dev/null 2>&1 ; then
        echo $"" >&2
        echo $"Error! rpmbuild not present." >&2
        echo $"Install the rpm-build package." >&2
        exit 1
    fi

    local kmodtool=$(rpm -ql redhat-rpm-config | grep kmodtool)
    #Check that the kmodtool is present
    if [ -z "$kmodtool" ]; then
        echo $"Error! kmodtool not present." >&2
        echo $"Install redhat-rpm-config package." >&2
        exit 1
    fi

    # Check that the createrepo command is present
    if ! which createrepo >/dev/null 2>&1 ; then
        echo $"" >&2
        echo $"Error! createrepo not present." >&2
        echo $"Install the createrepo package." >&2
        exit 1
    fi

    echo $""
    if [ -n "$specfile" -a -e "$dkms_tree/$module/$module_version/source/$specfile" ]; then
        echo $"Using $dkms_tree/$module/$module_version/source/$specfile"
        SPECFILE="$dkms_tree/$module/$module_version/source/$specfile"
    elif [ -e "/etc/dkms/template-dkms-redhat-kmod.spec" ]; then
        echo $"Using /etc/dkms/template-dkms-redhat-kmod.spec"
        SPECFILE="/etc/dkms/template-dkms-redhat-kmod.spec"
    else
        echo $"" >&2
        echo $"Cannot find /etc/dkms/template-dkms-redhat-kmod.spec which is needed by" >&2
        echo $"DKMS in order to make Redhat driver disk v3." >&2
        exit 5
    fi
    # Set up temporary build directory for build
    rm -rf "$dkms_tree/$module/$module_version/build"
    cp -a "$dkms_tree/$module/$module_version/source/" "$dkms_tree/$module/$module_version/build"

    cd "$dkms_tree/$module/$module_version/build"

    # Run the pre_build script
    if [ -n "$pre_build" ] && [ -x `echo "$dkms_tree/$module/$module_version/source/$pre_build" | sed 's/ .*//'` ]; then
        echo $""
        echo $"Running the pre_build script:"
        $dkms_tree/$module/$module_version/build/$pre_build
    fi

    # Apply any patches
    local index=0
    while [ $index -lt ${#patch_array[@]} ]; do
        if ! [ -e "$dkms_tree/$module/$module_version/build/patches/${patch_array[$index]}" ]; then
            echo $"" >&2
            echo $"Error!  Patch ${patch_array[$index]} as specified in dkms.conf cannot be" >&2
            echo $"found in $dkms_tree/$module/$module_version/build/patches/." >&2
            exit 5
        fi
        invoke_command "patch -p1 < ./patches/${patch_array[$index]}" "applying patch ${patch_array[$index]}"
        if [ "$?" -ne 0 ]; then
            echo $"" >&2
            echo $"Error! Application of patch ${patch_array[$index]} failed." >&2
            echo $"Check $dkms_tree/$module/$module_version/build/ for more information." >&2
                report_build_problem
            exit 6
        fi
        index=$(($index+1))
    done
    # Create temp dirs and copy files for build
    local temp_dir_name=`mktemp -d $tmp_location/dkms.XXXXXX`
    trap 'rm -rf $temp_dir_name' EXIT HUP TERM
    mkdir -p ${temp_dir_name}/{disk,BUILD,RPMS,SRPMS,SPECS,SOURCES}
    cp ${SPECFILE} ${temp_dir_name}/SPECS/$module.spec
    cp -rax $dkms_tree/$module/$module_version/build/ $temp_dir_name/SOURCES/$module-$module_version/
    # Clean the build directory
    rm -rf "$dkms_tree/$module/$module_version/build"
    cd $temp_dir_name/SOURCES
    invoke_command "tar -jcvf $temp_dir_name/SOURCES/$module-$module_version.tar.bz2 $module-$module_version/" "creating source tarball"
    local i=0
    # Build RPMS
    while [ $i -lt ${#kernelver[@]} ]; do
        invoke_command "LC_ALL=C rpmbuild --define \"_topdir ${temp_dir_name}\" --define \"version $module_version\" --define \"module_name $module\" --define \"kernel_version ${kernelver[$i]}\" -bb --target ${arch[$i]} ${temp_dir_name}/SPECS/$module.spec > ${temp_dir_name}/rpmbuild.log 2>&1" "rpmbuild"
        if [ "$?" -ne 0 ]; then
            echo $"" >&2
            echo $"Error! There was a problem creating your kmod." >&2
            cat ${temp_dir_name}/rpmbuild.log >&2
            exit 7
        fi
        local kabi_whitelist=`rpm -ql kabi-whitelists | grep ${arch[$i]}`
        if [ $kabi_whitelist ]; then
            local module_file=`rpm -qlp ${temp_dir_name}/RPMS/${arch[$i]}/kmod-${module}-${module_version}* | grep ${module}.ko`
            cd ${temp_dir_name}/
            rpm2cpio ${temp_dir_name}/RPMS/${arch[$i]}/kmod-${module}-${module_version}* | cpio -id --quiet .${module_file}
            cd - > /dev/null
            local mod_symbols=( $(modprobe --dump-modversions ${temp_dir_name}/${module_file} | cut -f2) )
            local miss_sym_count=0
            local missing_symbols
            for ((i=0; i < "${#mod_symbols[@]}"; i++))
            do
               if [ -z "`grep -o ${mod_symbols[${i}]} ${kabi_whitelist}`" ]; then
                   missing_symbols[$miss_sym_count]="${mod_symbols[${i}]}"
                   miss_sym_count=$(($miss_sym_count+1))
               fi
            done
            if [ $miss_sym_count -ne 0 ]; then
                echo $"" >&2
                echo $"WARNING: ${module}-${module_version} is using following kernel symbols that are not in the ABI whitelist:"
                echo $"----------------------------------"
                for missing_symbol in ${missing_symbols[*]}
                do
                    echo "$missing_symbol"
                done
                echo $"----------------------------------"
                echo $"" >&2
            else
                echo $"NOTICE: ${module}-${module_version} module seems to use only official Red Hat ABI."
            fi
        else
            echo $"WARNING:${module}-${module_version} module is not checked against Red Hat ABI whitelist."
            echo $"Install 'kabi-whitelists' package and build driver disk again to run the ABI compliance test."
        fi
        i=$(($i + 1))
    done

    i=0
    while [ $i -lt ${#arch[@]} ]; do
        invoke_command "createrepo --pretty ${temp_dir_name}/RPMS/${arch[$i]}" "creating repo"
        if [ "$?" -ne 0 ]; then
            echo $"" >&2
            echo $"Error! There was a problem creating repository." >&2
            exit 7
        fi
        i=$(($i + 1))
    done

    echo "$module-$module_version driver disk" > "${temp_dir_name}/disk/rhdd3"
    mkdir ${temp_dir_name}/disk/rpms
    cp -rax ${temp_dir_name}/RPMS/* ${temp_dir_name}/disk/rpms/

    local suffix="$(driver_disk_suffix)"
    local image_dir="$dkms_tree/$module/$module_version/driver_disk"
    local image_name="$module-$module_version-dd.$suffix"
    echo $""
    echo $"Creating driver disk on $media media:"
    cd "${temp_dir_name}/disk"
    mkdir -p "$image_dir"
    rm -f "$image_dir/$image_name"
    make_driver_disk_media "$image_dir/$image_name" "${temp_dir_name}/disk"
    rm -rf $temp_dir_name

    echo $""
    echo $"Disk image location: $image_dir/$image_name"

    trap > /dev/null 2>&1
}

#############################
####                     ####
#### Program Starts Here ####
####                     ####
#############################

# Set a standard path
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/lib/dkms"

# Ensure files and directories we create are readable to anyone,
# since we aim to build as a non-root user
umask 022

# Unset environment variables that may interfere with the build
unset CC CXX CFLAGS CXXFLAGS LDFLAGS

# Set important variables
current_kernel=$(uname -r)
current_os=$(uname -s)
dkms_tree="/var/lib/dkms"
source_tree="/usr/src"
install_tree="/lib/modules"
tmp_location=${TMPDIR:-/tmp}
verbose=""
symlink_modules=""
dkms_frameworkconf="/etc/dkms/framework.conf"

# These can come from the environment or the config file
[[ ! ${ADDON_MODULES_DIR} && -e /etc/sysconfig/module-init-tools ]] && . /etc/sysconfig/module-init-tools
addon_modules_dir="${ADDON_MODULES_DIR}"
[[ ! ${addon_modules_dir} ]] && running_distribution="$(distro_version)"
weak_modules="${WEAK_MODULES_BIN}"

# Source in /etc/dkms/framework.conf
[ -e $dkms_frameworkconf ] && . $dkms_frameworkconf 2>/dev/null

# Clear out command line argument variables
module=""
module_version=""
template_kernel=""
distro=""
media=""
release=""
conf=""
kernel_config=""
archive_location=""
kernel_source_dir=""
ksourcedir_fromcli=""
action=""
force=""
force_version_override=""
no_prepare_kernel=""
no_clean_kernel=""
binaries_only=""
source_only=""
all=""
module_suffix=""
module_uncompressed_suffix=""
module_compressed_suffix=""
rpm_safe_upgrade=""
size="1440";
specfile=""
legacy_postinst="1"
declare -a directive_array=() kernelver=() arch=()
weak_modules=''
last_mvka=''
last_mvka_conf=''
try_source_tree=''
die_is_fatal="yes"
[ -x /sbin/weak-modules ] && weak_modules='/sbin/weak-modules'
[ -x /usr/lib/module-init-tools/weak-modules ] && weak_modules='/usr/lib/module-init-tools/weak-modules'
no_depmod=""

action_re='^(remove|(auto|un)?install|match|mk(driverdisk|tarball|rpm|deb|bmdeb|dsc|kmp)|(un)?build|add|status|ldtarball)$'

# Parse command line arguments
while (($# > 0)); do
    case $1 in
        --dkmsframework*)
            read_arg dkms_frameworkconf "$1" "$2" || shift
            #immediately load this config
            . $dkms_frameworkconf 2> /dev/null
            ;;
        --module*|-m)
            read_arg _mv "$1" "$2" || shift
            parse_moduleversion "$_mv"
            ;;
        -v)
            read_arg module_version "$1" "$2" || shift
            ;;
        --kernelver*|-k)
            read_arg _ka "$1" "$2" || shift
            parse_kernelarch "$_ka"
            ;;
        --distro*|-d)
            read_arg distro "$1" "$2" || shift
            ;;
        --media*)
            read_arg media "$1" "$2" ||shift
            ;;
        --release*|-r)
            read_arg release "$1" "$2" || shift
            ;;
        --templatekernel*)
            read_arg template_kernel "$1" "$2" || shift
            ;;
        -c)
            read_arg conf "$1" "$2" || shift
            ;;
        --quiet|-q)
            exec >/dev/null 2>&1
            ;;
        --version|-V)
            echo $"dkms-2.8.7"
            exit 0
            ;;
        --no-prepare-kernel)
            no_prepare_kernel="no-prepare-kernel"
            ;;
        --no-clean-kernel)
            no_clean_kernel="no-clean-kernel"
            ;;
        --no-initrd)
            no_initrd="no-initrd"
            ;;
        --binaries-only)
            binaries_only="binaries-only"
            ;;
        --source-only)
            source_only="source-only"
            ;;
        --force)
            force="true"
            ;;
        --force-version-override)
            force_version_override="true"
            ;;
        --all)
            all="true"
            ;;
        --verbose)
            verbose="true"
            ;;
        --rpm_safe_upgrade)
            rpm_safe_upgrade="true"
            ;;
        --dkmstree*)
            read_arg dkms_tree "$1" "$2" || shift
            ;;
        --sourcetree*)
            read_arg source_tree "$1" "$2" || shift
            ;;
        --installtree*)
            read_arg install_tree "$1" "$2" || shift
            ;;
        --symlink-modules)
            symlink_module="true"
            ;;
        --config*)
            read_arg kernel_config "$1" "$2" || shift
            ;;
        --archive*)
            read_arg archive_location "$1" "$2" || shift
            ;;
        --legacy-postinst*)
            read_arg legacy_postinst "$1" "$2" || shift
            ;;
        --arch*|-a)
            read_arg _aa "$1" "$2" || shift
            arch[${#arch[@]}]="$_aa"
            ;;
        --size*)
            read_arg size "$1" "$2" || shift
            ;;
        --kernelsourcedir*)
            read_arg kernel_source_dir "$1" "$2" || shift
            ksourcedir_fromcli="true"
            ;;
        --directive*)
            read_arg _da "$1" "$2" || shift
            directive_array[${#directive_array[@]}]="$_da"
            ;;
        --spec*)
            read_arg specfile "$1" "$2" || shift
            ;;
        --no-depmod)
            no_depmod="true"
            ;;
        --debug)
            export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): '
            set -x
            ;;
        -j)
            read_arg parallel_jobs "$1" "$2" || shift
            ;;
        -*|--*)
            error $" Unknown option: $1"
            show_usage
            exit 2
            ;;
        *)
            if [[ $1 =~ $action_re ]]; then
                action="$action $1" # Add actions to the action list
            elif [[ -f $1 && $1 = *dkms.conf ]]; then
                try_source_tree="${1%dkms.conf}./" # Flag as a source tree
            elif [[ -d $1 && -f $1/dkms.conf ]]; then
                try_source_tree="$1" # ditto
            elif [[ -f $1 ]]; then
                archive_location="$1" # It is a file, assume it is an archive.
            elif [[ ! $module ]]; then
                parse_moduleversion "$1" # Assume it is a module/version pair.
            else
                warn $"I do not know how to handle $1."
            fi
            ;;
    esac
    shift
done

# Sanity checking

# Error out if binaries-only is set and source-only is set
if [[ $binaries_only && $source_only ]]; then
    die 8 $" You have specified both --binaries-only and --source-only." \
        $"You cannot do this."
fi

# Error if # of arches doesn't match # of kernels
if (( ${#kernelver[@]} != ${#arch[@]} && \
    ${#arch[@]} > 1 )); then
    die 1 $" If more than one arch is specified on the command line, then there" \
        $"must be an equal number of kernel versions also specified (1:1 relationship)."
fi

# Check that kernel version and all aren't both set simultaneously
if [[ $kernelver && $all ]]; then
    die 2 $" You cannot specify a kernel version and also specify" \
        $"--all on the command line."
fi

# Check that arch and all aren't both set simultaneously
if [[ $arch && $all ]]; then
    die 3 $" You cannot specify an arch and also specify" \
        $"--all on the command line."
fi

# If initramfs/initrd rebuild is not requested, skip it with Redhat's weak-modules
if [[ $no_initrd && $weak_modules ]]; then
    weak_modules_no_initrd="--no-initramfs"
fi

# Default to -j<number of CPUs>
parallel_jobs=${parallel_jobs:-$(get_num_cpus)}

# Make sure we're not passing -j0 to make; treat -j0 as just "-j"
[[ "$parallel_jobs" = 0 ]] && parallel_jobs=""

# Run the specified action
if [ -z "$action" ]; then
    show_usage
    die 4 $"No action was specified."
fi

for action_to_run in $action; do
    setup_kernels_arches "$action_to_run"
    case "$action_to_run" in
    remove)
        check_root && remove_module
        ;;
    unbuild)
        check_root && unbuild_module
        ;;
    install)
        check_root && check_all_is_banned "install" && install_modules
        ;;
    autoinstall)
        check_root && autoinstall
        ;;
    match)
        check_root && have_one_kernel "match" && run_match
        ;;
    uninstall)
        check_root && uninstall_module
        ;;
    mkdriverdisk)
        check_root && make_driver_disk
        ;;
    build)
        [ ! -w "$dkms_tree" ] && die 1 $"No write access to create a DKMS tree at ${dkms_tree}"
        check_all_is_banned "build" && build_modules
        ;;
    add)
        check_root && check_all_is_banned "add" && add_module
        ;;
    mktarball)
        make_tarball
        ;;
    mkrpm)
        make_rpm
        ;;
    mkdeb)
        make_debian "deb"
        ;;
    mkbmdeb)
        make_debian "bmdeb"
        ;;
    mkdsc)
        make_debian "dsc"
        ;;
    mkkmp)
        have_one_kernel "mkkmp" && make_kmp
        ;;
    status)
        show_status
        ;;
    ldtarball) # Make sure they're root if we're using --force
        if [[ $(id -u) != 0 ]] && [[ $force = true ]]; then
            die 1 $"You must be root to use this command with the --force option."
        fi
        load_tarball && add_module
        ;;
    '')
        error $"No action was specified."
        show_usage
        ;;
    *)
        error $"Unknown action specified: $action_to_run"
        show_usage
        ;;
    esac
done
cosplay – Verilere bak
Menu
  • Top 10

Verilere bak

Follow us
  • facebook
  • twitter
Search
Login
Create
Menu

Verilere bak

Login

You are here:

  1. Home
  2. Tag Archives: cosplay

cosplay

Latest stories

Wait, Whaaat? These 17 Paintings Cost Over 10 Million Bucks

  • facebook
  • twitter

Arşivler

Kategoriler

Disclaimer

This demo site is only for demonstration purposes. All images are copyrighted to their respective owners. All content cited is derived from their respective sources.

© 2017 bring the pixel. Remember to change this

  • Home
  • Contact us
Back to Top
Close
  • Top 10
  • Home
  • Animals
  • Funny
  • WOW
  • WTF
  • Features
  • facebook
  • twitter
Create

Log In

Sign In

Forgot password?

Forgot password?

Enter your account data and we will send you a link to reset your password.

Back to Login

Your password reset link appears to be invalid or expired.

Log in

Privacy Policy

Accept

Add to Collection

  • Public collection title

  • Private collection title

No Collections

Here you'll find all collections you've created before.

Hey Friend!
Before You Go…

Get the best viral stories straight into your inbox before everyone else!

Don't worry, we don't spam

Close

Newsletter

Don’t miss out on new posts!

Don't worry, we don't spam

Close