Permalink
Cannot retrieve contributors at this time
Fetching contributors…
| #!/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 | |
| # | |
| # 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_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" | |
| # 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() { | |
| KVER=$1 | |
| case ${current_os} in | |
| Linux) DIR="/lib/modules/$KVER/build" ;; | |
| GNU/kFreeBSD) DIR="/usr/src/kfreebsd-headers-$KVER/sys" ;; | |
| esac | |
| echo $DIR | |
| } | |
| _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" | |
| echo $" | mkdriverdisk | mktarball | ldtarball | mkrpm | mkkmp | mkdeb | status }" | |
| echo $" [options] = [-m module] [-v module-version] [-k kernel-version] [-a arch]" | |
| echo $" [-d distro] [-c dkms.conf-location] [-q] [--force] [--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 | |
| } | |
| # 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_suffix=".ko" | |
| [[ $(VER $kernel_test) < $(VER 2.5) ]] && module_suffix=".o" | |
| } | |
| set_kernel_source_dir() | |
| { | |
| # $1 = the kernel to base the directory on | |
| kernel_source_dir="$(_get_kernel_dir "$1")" | |
| } | |
| # 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 | |
| if [[ $all ]]; then | |
| die 5 $"The action $1 does not support the --all" \ | |
| $"parameter." | |
| fi | |
| } | |
| # 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) | |
| kernels_arches_default="yes" | |
| 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 deliberatly 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 installtion 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" | |
| # 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(){ | |
| unset 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 | |
| set_module_suffix | |
| read -a kernels_module < <(find $lib_tree -name ${4}$module_suffix) | |
| if [ -z $kernels_module ]; 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 | |
| else | |
| return 0 | |
| fi | |
| 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="$dkms_tree/$module/$module_version/$1/$2/module/${4}$module_suffix" | |
| 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]} && ! $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 | |
| if [[ $file = /etc/sysconfig/kernel ]]; then | |
| sed "${sa_sck_o[*]}" "$file" > "$temp_dir_name/${file##*/}.new" | |
| else | |
| sed "${sa_mc_o[*]}" "$file" > "$temp_dir_name/${file##*/}.new" | |
| fi | |
| if ! mod_diff=$(diff -u "$temp_dir_name/${file##*/}.new" "$file"); then | |
| echo $"$file updated to replace obsoleted module references:" | |
| echo "$mod_diff" | |
| cp -fp "$temp_dir_name/${file##*/}.new" "$file" | |
| rm -f "$temp_dir_name/${file##*/}.new" | |
| 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() | |
| ( | |
| [[ -e /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 $"Invalid number of arguments passed." \ | |
| $"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 | |
| } | |
| # 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 | |
| # 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 | |
| # 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 the conf file for sanity | |
| read_conf_or_die "$kernelver" "$arch" "$conf" | |
| # Create the necessary dkms tree structure | |
| echo $"" | |
| echo $"Creating symlink $dkms_tree/$module/$module_version/source ->" | |
| echo $" $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" | |
| echo $"" | |
| echo $"DKMS: add completed." | |
| } | |
| # 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 echo $"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 | |
| } | |
| [[ $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 dkms.conf for this module includes a BUILD_EXCLUSIVE directive which" \ | |
| $"does not match this kernel/arch. 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 | |
| # 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_suffix ]] && continue | |
| report_build_problem 7 \ | |
| $" Build of ${built_module_name[$count]}$module_suffix failed for: $kernelver ($arch)" \ | |
| $"Consult the 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_suffix" | |
| 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" | |
| } | |
| build_module() | |
| { | |
| prepare_build | |
| do_build | |
| clean_build | |
| echo $"" | |
| echo $"DKMS: build completed." | |
| } | |
| # 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 | |
| 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 | |
| force_installation $module && echo "Forcing installation of $module" \ | |
| && force="true" | |
| # 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 module_count=$(find $lib_tree -name ${dest_module_name[$count]}$module_suffix -type f | wc -l | awk {'print $1'}) | |
| echo $" - Original module" | |
| if [[ -L $dkms_tree/$module/kernel-$kernelver-$arch && \ | |
| -e $dkms_tree/$module/original_module/$kernelver/$arch/${dest_module_name[$count]}$module_suffix ]]; then | |
| echo $" - An original module was already stored during a previous install" | |
| elif ! [[ -L $dkms_tree/$module/kernel-$kernelver-$arch ]]; then | |
| local archive_pref1="$lib_tree/extra/${dest_module_name[$count]}$module_suffix" | |
| local archive_pref2="$lib_tree/updates/${dest_module_name[$count]}$module_suffix" | |
| local archive_pref3="$lib_tree${dest_module_location[$count]}/${dest_module_name[$count]}$module_suffix" | |
| local archive_pref4="" | |
| ((module_count == 1)) && archive_pref4=$(find $lib_tree -name ${dest_module_name[$count]}$module_suffix -type f) | |
| 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 ${dest_module_name[$count]}$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 $lib_tree -name ${dest_module_name[$count]}$module_suffix -type f); do | |
| dup_tree="${module_dup#$lib_tree}"; | |
| dup_tree="${dup_tree/${dest_module_name[$count]}$module_suffix}" | |
| 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" | |
| cp -f $symlink "$base_dir/module/${dest_module_name[$count]}$module_suffix" "$install_tree/$kernelver${dest_module_location[$count]}/${dest_module_name[$count]}$module_suffix" | |
| 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." \ | |
| $"DKMS: Install Failed (depmod problems). Module rolled back to built state." | |
| exit 6 | |
| } | |
| # Make the newly installed modules available immediately | |
| find /sys/devices -name modalias -print0 | xargs -0 cat | xargs modprobe -a -b -q | |
| if [ -f /lib/systemd/system/systemd-modules-load.service ]; then | |
| systemctl restart systemd-modules-load.service | |
| fi | |
| # 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." \ | |
| $"DKMS: Install Failed (mkinitrd problems). Module rolled back to built state." | |
| } | |
| echo $"" | |
| echo $"DKMS: install completed." | |
| # 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 | |
| for ((count=0; count < ${#built_module_name[@]}; count++)); do | |
| real_dest_module_location="$(find_actual_dest_module_location $1 $count $2 $3)" | |
| echo "$install_tree/$2${real_dest_module_location}/${dest_module_name[$count]}$module_suffix" | |
| 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" | |
| for m in "${dest_module_name[@]}"; do | |
| [[ -f $d/module/$m.ko || -f $d/module/$m.o ]] || 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="${dkms_tree}/${module}/kernel-${kernelver}-${arch}/module/${dest_module_name[$count]}${module_suffix}" | |
| for l in $locations; do | |
| installed="${install_tree}/${kernelver}${l}/${dest_module_name[${count}]}${module_suffix}" | |
| if [[ -f ${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 $"" | |
| echo $"-------- Uninstall Beginning --------" | |
| echo $"Module: $module" | |
| echo $"Version: $module_version" | |
| echo $"Kernel: $1 ($2)" | |
| echo $"-------------------------------------" | |
| 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 $"" | |
| echo $"Status: 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_suffix" | |
| dir_to_remove="${real_dest_module_location#/}" | |
| while [ "${dir_to_remove}" != "${dir_to_remove#/}" ]; do | |
| dir_to_remove="${dir_to_remove#/}" | |
| done | |
| (cd "$install_tree/$1" && rm -rf "${dir_to_remove}/*" && rmdir -p "${dir_to_remove}" || true) | |
| echo $" - Original module" | |
| if [[ -e $dkms_tree/$module/original_module/$1/$2/${dest_module_name[$count]}$module_suffix ]]; 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 "$dkms_tree/$module/original_module/$1/$2/${dest_module_name[$count]}$module_suffix" \ | |
| "$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 -rf "$dkms_tree/$module/kernel-$1-$2" | |
| #Remove modules from dkms built tree | |
| rm -rf "$dkms_tree/$module/$module_version/$1" | |
| else | |
| echo $"" | |
| echo $"Status: 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" | |
| echo $"" | |
| echo $"DKMS: uninstall completed." | |
| } | |
| # 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 | |
| [[ -d $dkms_tree/$module ]] || die 2 \ | |
| $"There are no instances of module: $module" \ | |
| $"located in the DKMS tree." | |
| # Make sure that its installed in the first place | |
| [[ -d $dkms_tree/$module/$module_version ]] || die 3 \ | |
| $"The module/version combo: $module-$module_version" \ | |
| $"is not located in the DKMS tree." | |
| # Read the conf file | |
| read_conf_or_die "$kernelver" "$arch" | |
| # Only do stuff if module/module version is currently installed | |
| local kernel_symlink=$(readlink -f "$dkms_tree/$module/kernel-$kernelver-$arch") | |
| [[ $kernel_symlink = $dkms_tree/$module/$module_version/$kernelver/$arch ]] || die 5 \ | |
| $"The module $module $module_version is not currently installed." \ | |
| $"This module is not currently ACTIVE for kernel $kernelver ($arch)." | |
| do_uninstall "$kernelver" "$arch" | |
| } | |
| # Unregister a DKMS module. This uninstalls any installed modules along the way. | |
| remove_module() | |
| { | |
| # Check that the right arguments were passed | |
| if [[ ! ($module && $module_version) || $kernels_arches_default ]]; then | |
| die 1 $"Invalid number of parameters passed." \ | |
| $"Usage: remove <module>/<module-version> --all" \ | |
| $" or: remove <module>/<module-version> -k <kernel-version>" | |
| fi | |
| # Check that $module is in the dkms tree | |
| if ! [[ -d $dkms_tree/$module/$module_version ]]; then | |
| die 3 $"There are no instances of module: $module" \ | |
| $"$module_version located in the DKMS tree." | |
| fi | |
| local i | |
| for ((i=0; i < ${#kernelver[@]}; i++)); do | |
| # Make sure its there first before removing | |
| if ! [[ -d $dkms_tree/$module/$module_version/${kernelver[$i]}/${arch[$i]} ]]; then | |
| die 4 $"There is no instance of $module $module_version" \ | |
| $"for kernel ${kernelver[$i]} (${arch[$i]}) located in the DKMS tree." | |
| fi | |
| # 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 $"DKMS: Remove cancelled because --rpm_safe_upgrade scenario detected." | |
| done | |
| fi | |
| # Read the conf file | |
| read_conf_or_die "${kernelver[$i]}" "${arch[$i]}" | |
| do_uninstall "${kernelver[$i]}" "${arch[$i]}" | |
| # Delete the $kernel_version/$arch_used part of the tree | |
| rm -rf "$dkms_tree/$module/$module_version/${kernelver[$i]}/${arch[$i]}" | |
| [[ $(find $dkms_tree/$module/$module_version/${kernelver[$i]}/* -maxdepth 0 -type d 2>/dev/null) ]] || \ | |
| rm -rf "$dkms_tree/$module/$module_version/${kernelver[$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 $"" | |
| echo $"------------------------------" | |
| echo $"Deleting module version: $module_version" | |
| echo $"completely from the DKMS tree." | |
| echo $"------------------------------" | |
| rm -rf "$dkms_tree/$module/$module_version" | |
| echo $"Done." | |
| 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="$dkms_tree/$1/$2/$3/$4/module/${dest_module_name[$count]}$module_suffix" | |
| if ! [[ -e $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")" | |
| if ! diff -q "$tree_mod" "$install_tree/$3${real_dest}/${dest_module_name[$count]}$module_suffix" >/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 inconvienent. | |
| 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 $"" | |
| 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]}" | |
| if ! [[ -e $dkms_tree/$module/$module_version/${kernelver[$i]}/${arch[$i]}/module/${dest_module_name[$count]}$module_suffix ]]; 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 "$dkms_tree/$module/$module_version/${kernelver[$i]}/${arch[$i]}/module/${dest_module_name[$count]}$module_suffix" "$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 "$dkms_tree/$module/$module_version/${kernelver[$i]}/${arch[$i]}/module/${dest_module_name[$count]}$module_suffix" "$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" | |
| echo $"" | |
| echo $"DKMS: mkdriverdisk completed." | |
| } | |
| 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_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" | |
| echo $"" | |
| echo $"DKMS: mkdriverdisk completed." | |
| } | |
| 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 --force -9 "$tarball_dest/$tarball_name" | |
| ;; | |
| bz2) | |
| bzip2 --force -9 "$tarball_dest/$tarball_name" | |
| ;; | |
| xz) | |
| xz --force -9 "$tarball_dest/$tarball_name" | |
| ;; | |
| esac | |
| echo $"" | |
| echo $"DKMS: mktarball completed." | |
| } | |
| # 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, 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 | |
| echo $"" | |
| echo $"DKMS: ldtarball completed." | |
| [[ $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 $"" | |
| echo $"---- Match Beginning ----" | |
| echo $"Module: $template_module" | |
| echo $"Version: $template_version" | |
| echo $"-------------------------" | |
| # 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 | |
| # Done | |
| echo $"" | |
| echo $"DKMS: match completed." | |
| } | |
| 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/.*/::' | |
| echo $"" | |
| echo $"DKMS: mkrpm completed." | |
| 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/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 ((UID != 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//_/-} | |
| # 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 | |
| # Copy in the source tree | |
| if [[ ! $binaries_only ]]; then | |
| invoke_command "cp -Lpr '$dkms_tree/$module/$module_version/source' '$temp_dir_debian/$module-$module_version'" "Copying source tree" | |
| fi | |
| # Only if we are shipping binary modules, make a .tgz for the deb | |
| local archive_location="$dkms_tree/$module/$module_version/tarball/$module-$module_version.dkms.tar.gz" | |
| if [[ ! $source_only ]]; then | |
| 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 | |
| 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 "dpkg-buildpackage -S -us -uc 1>/dev/null" "Building source package" || \ | |
| die 7 $"There was a problem creating your ${create_type}." | |
| echo $"" | |
| echo $"DKMS: mk${create_type} completed." | |
| 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 "dpkg-buildpackage -rfakeroot -d -b -us -uc 1>/dev/null" "Building binary package" || \ | |
| die 7 $"There was a problem creating your ${create_type}." | |
| echo $"" | |
| echo $"DKMS: mk${create_type} completed." | |
| invoke_command "mv '$temp_dir/${debian_package}-dkms_${module_version}_all.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 $"The module/version combo: $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 convienent 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() { | |
| ((UID == 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" | |
| echo $"" | |
| echo $"DKMS: mkkmp completed." | |
| 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"; 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" | |
| echo $"" | |
| echo $"DKMS: mkdriverdisk completed." | |
| 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="" | |
| no_prepare_kernel="" | |
| no_clean_kernel="" | |
| binaries_only="" | |
| source_only="" | |
| all="" | |
| module_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|dsc|kmp)|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: [INSERT_VERSION_HERE]" | |
| 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" | |
| ;; | |
| --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 | |
| ;; | |
| install) | |
| check_root && install_modules | |
| ;; | |
| autoinstall) | |
| check_root && autoinstall | |
| ;; | |
| match) | |
| check_root && have_one_kernel && run_match | |
| ;; | |
| uninstall) | |
| check_root && have_one_kernel && uninstall_module | |
| ;; | |
| mkdriverdisk) | |
| check_root && make_driver_disk | |
| ;; | |
| build) | |
| build_modules | |
| ;; | |
| add) | |
| add_module | |
| ;; | |
| mktarball) | |
| make_tarball | |
| ;; | |
| mkrpm) | |
| make_rpm | |
| ;; | |
| mkdeb) | |
| make_debian "deb" | |
| ;; | |
| mkdsc) | |
| make_debian "dsc" | |
| ;; | |
| mkkmp) | |
| have_one_kernel && make_kmp | |
| ;; | |
| status) | |
| show_status | |
| ;; | |
| ldtarball) # Make sure they're root if we're using --force | |
| if ((UID != 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 |