commit d3ade7a35cd53a82bf97c873c348491eaa0b0d5135c1fcb967230ed095f891a1 Author: Andreas Jaeger Date: Fri Nov 23 15:19:32 2012 +0000 Accepting request 142369 from home:jengelh:dev should have been part of 141930 OBS-URL: https://build.opensuse.org/request/show/142369 OBS-URL: https://build.opensuse.org/package/show/Base:System/suse-module-tools?expand=0&rev=1 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57affb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.osc diff --git a/10-unsupported-modules.conf b/10-unsupported-modules.conf new file mode 100644 index 0000000..8aa4ec6 --- /dev/null +++ b/10-unsupported-modules.conf @@ -0,0 +1,10 @@ +# +# Every kernel module has a flag 'supported'. If this flag is not set loading +# this module will taint your kernel. You will not get much help with a kernel +# problem if your kernel is marked as tainted. In this case you firstly have +# to avoid loading of unsupported modules. +# +# Setting allow_unsupported_modules 1 enables loading of unsupported modules +# by modprobe, setting allow_unsupported_modules 0 disables it. This can +# be overriden using the --allow-unsupported-modules commandline switch. +allow_unsupported_modules 1 diff --git a/README.SUSE b/README.SUSE new file mode 100644 index 0000000..d065853 --- /dev/null +++ b/README.SUSE @@ -0,0 +1,19 @@ +Please don't edit /etc/modprobe.conf. Place your settings into +/etc/modprobe.conf.local instead. + + +To avoid loading backup files of various tools and editors, modprobe skips +files under /etc/modprobe.d/ that have the following prefixes + +"." +"~" + +and the following suffixes + +".rpmsave" +".rpmorig" +".rpmnew" +".bak" +".YaST2save" +".-" +"~" diff --git a/depmod-00-system.conf b/depmod-00-system.conf new file mode 100644 index 0000000..f99849e --- /dev/null +++ b/depmod-00-system.conf @@ -0,0 +1,17 @@ +# +# /etc/depmod.conf - configuration file for the depmod(8) command, +# for its format see depmod.conf(5). +# +# Please don't edit this file, place your settings into the /etc/depmod.d +# directory. + + +# search order: +# 1 updates/ (KMPs) +# 2 extra/ (KMPs or manually compiled modules) +# 3 weak-updates/ (KMPs built for older kernels) +# 4 everything else +search updates extra weak-updates built-in + +# do not generate modules.*map files +make_map_files no diff --git a/driver-check.sh b/driver-check.sh new file mode 100644 index 0000000..69cc34a --- /dev/null +++ b/driver-check.sh @@ -0,0 +1,314 @@ +#!/bin/bash + +VERSION="0.5" +MAINTAINER="Michal Marek " +USAGE="Usage: ${0##*/} [-o|--out output-file]" + +errors=0 +warnings=0 + +trap 'rm -rf "$tmp"' EXIT +tmp=$(mktemp -d) + +rpm() +{ + # rpm tends to send localized error messages to stdout :-( + LC_ALL=C command rpm "$@" +} + +file_owner() +{ + local f=$1 + + if (cd "$tmp/rpms"; grep -lFx "$f" *); then + return + fi + rpm -qf "$f" +} + +_explain_called=() +explain() +{ + local caller=${BASH_LINENO[0]} + + if test -n "${_explain_called[$caller]}"; then + return + fi + _explain_called[$caller]=1 + echo "$*" +} + +error() +{ + echo "ERROR: $*" + let errors++ +} + +warning() +{ + echo "warning: $*" >&2 + let warnings++ +} + +check_system() +{ + if test ! -x /usr/lib/module-init-tools/weak-modules2; then + echo "This tool only works on SLE11 and later systems" >&2 + exit 1 + fi + if ! zypper search >/dev/null; then + echo "Cannot run zypper, please correct the above problem" >&2 + exit 1 + fi +} + +check_rpm() +{ + local rpm=$1 name=${1%-*-*} + + # ignore changes to %config and %doc files and ignore changed mtimes + if rpm -V "$rpm" | grep -Ev '^[^ ]{8,} [cd] |^\.{7}T\.* '; then + error "$rpm was not installed correctly (see above)" + fi + # this is ugly. Apparently zypper insist on the progress messages and + # the ascii table, so grep for the table row. + if ! LC_ALL=C zypper -A search -t package -u -s --match-exact "$name" \ + | grep -qe ---; then + error "$rpm: no update repositories found" + fi +} + +check_kernel_package() +{ + local kernel=$1 + + if ! rpm -q --qf '%{description}\n' "$kernel" | grep -q '^GIT '; then + error "$kernel does not look like a SUSE kernel package (no commit id)" + fi + if ! rpm -q --qf '%{postin}\n' "$kernel" | grep -q 'weak-modules2'; then + error "$kernel does not look like a SUSE kernel package (wrong %post script)" + fi +} + +check_krel() +{ + local krel=$1 system_map module_symvers msg res args bad=false + local mit_version + + system_map="/boot/System.map-$krel" + module_symvers="/boot/symvers-$krel.gz" + if ! test -e "$system_map"; then + error "$system_map not found" + bad=true + fi + if ! test -e "$module_symvers"; then + error "$module_symvers not found" + bad=true + fi + if $bad; then + explain "Each kernel must install /boot/System.map-\$version and /boot/symvers-\$version.gz to be able to check module dependencies." + return + fi + set -- $(/sbin/depmod --version | sed -rn 's/.* ([0-9]+)\.([0-9]+)(\..*)?/\1 \2/p') + if test -n "$1" -a -n "$2"; then + let "mit_version = $1 * 100 + $2" + else + warning "Cannot determine module-init-tools version, this is a bug in the script" + mit_version=0 + fi + # depmod -E was introduced in 3.10 + if test "$mit_version" -ge 310; then + gzip -cd <"$module_symvers" >"$tmp/symvers" + args=(-E "$tmp/symvers") + else + args=(-F "$system_map") + fi + msg=$(/sbin/depmod -n -e "${args[@]}" "$krel" 2>&1 >/dev/null) + res=$? + if test -n "$msg" -o "$res" -ne 0; then + echo "$msg" + error "depmod $krel returned errors (exit code $res)" + explain "depmod must pass without errors otherwise KMP scripts will break" + fi + +} + +req_re='^(kernel\([^:]*:kernel[[:alnum:]_]*\)|ksym\([^:]*:(struct_module|module_layout)\)) = [0-9a-f]+' +check_kmp() +{ + local kmp=$1 prefix prev_krel krel path found_module=false + + if ! rpm -q --qf '%{postin}\n' "$kmp" | grep -q 'weak-modules2'; then + error "$kmp does not look like a SUSE kernel module package (wrong %post)" + fi + if ! rpm -q -R "$kmp" | grep -Eq "$req_re"; then + error "$kmp does not have proper dependencies" + fi + exec 3< <(sed -rn 's:^(/lib/modules)?/([^/]*)/(.*\.ko)$:\1 \2 \3:p' \ + "$tmp/rpms/$kmp") + while read prefix krel path <&3; do + found_module=true + if test "$prefix" != "/lib/modules"; then + error "$kmp installs modules outside of /lib/modules" + continue + fi + if test -z "$prev_krel"; then + prev_krel=$krel + elif test "$prev_krel" != "$krel"; then + error "$kmp installs modules for multiple kernel versions" + fi + case "$path" in + updates/* | extra/*) + ;; + weak-updates/*) + error "$kmp installs modules in weak-updates/ instead of updates/ or extra/" + explain "The weak-modules directory is reserved for automatically generated symlinks" + ;; + *) + error "$kmp installs modules in an invalid directory" + explain \ +"KMPs must install modules in the updates/ or extra/ subdirectories for the +weak-modules2 script to work" + ;; + esac + + done + if ! $found_module; then + error "$kmp does not contain any modules" + explain \ +"A KMP must contain it's modules in the rpm filelist, otherwise weak-modules2 +will not work" + fi +} + +check_ko() +{ + local ko=$1 kmp bad=false + + case "$ko" in + */weak-updates/*) + if test -L "$ko"; then + return + fi + esac + kmp=$(file_owner "$ko") + case "$kmp" in + kernel-* | *-kmp-*) ;; + *not\ owned\ by\ any\ package) + error "$ko is not owned by any package" + bad=true + ;; + *) + error "$ko is not packaged as a KMP" + bad=true + ;; + esac + if $bad; then + explain \ +"External kernel modules must be packaged as KMPs, see +http://developer.novell.com/wiki/index.php/Kernel_Module_Packages_Manuals" + fi +} + +options=$(getopt -n "${0##*/}" -o o:h --long out:,help -- "$@") +if test "$?" -ne 0; then + echo "$USAGE" >&2 + exit 1 +fi +eval set -- "$options" +logfile="driver-check-report.txt" +while :; do + case "$1" in + -o | --out) + logfile="$2" + shift 2 + ;; + -h | --help) + echo "${0##*/} $VERSION" + echo "$USAGE" + echo + echo "Please report bugs and enhancement requests to $MAINTAINER" + exit 0 + ;; + --) + shift + break + ;; + esac +done +if test $# -gt 0; then + echo "Unrecognized arguments: $*" >&2 + echo "$USAGE" >&2 + exit 1 +fi + +check_system + +# set up redirection +if test $logfile != "-"; then + if test -e "$logfile"; then + mv -f "$logfile" "$logfile~" + fi + if test -e /proc/self; then + exec 99> >(cat >"$logfile") + exec 1>&99 + exec 2> >(tee -a /proc/self/fd/99 >&2) + else + exec 1>"$logfile" + exec 2>"$logfile" + warning "/proc not mounted" + fi +fi +echo "${0##*/} $VERSION started at $(date -R)" >&2 + +check_rpm $(rpm -q --qf '%{n}-%{v}-%{r}\n' module-init-tools) + +mkdir -p "$tmp/rpms" +found_kernel=false +for rpm in $(rpm -qa --qf '%{n}-%{v}-%{r}\n' 'kernel-*' '*-kmp-*' | \ + /usr/lib/rpm/rpmsort); do + case "$rpm" in + kernel-source-* | kernel-syms-* | kernel-*-debug* | kernel-*-man-* | \ + kernel-*-devel-* | kernel-firmware-* | kernel-coverage-* | \ + kernel-docs-* | kernel-devel-*) + continue + esac + # store the filelist to speed up file_owner() + rpm -ql "$rpm" >"$tmp/rpms/$rpm" + check_rpm "$rpm" + case "$rpm" in + kernel-*) + check_kernel_package "$rpm" + found_kernel=true + ;; + *-kmp-*) + check_kmp "$rpm" + ;; + esac +done +if ! $found_kernel; then + warning "no kernel package found" +fi + +for krel in /lib/modules/*/kernel; do + krel=${krel%/kernel} + krel=${krel##*/} + check_krel "$krel" +done + +modules=($(find /lib/modules/ -name '*.ko')) +for module in "${modules[@]}"; do + check_ko "$module" +done + +echo "Found $errors error(s) and $warnings warning(s)" >&2 +if test "$logfile" != -; then + echo "Report written to $logfile at $(date -R)" >&2 +else + echo "Report finished at $(date -R)" >&2 +fi +if test $errors -eq 0; then + exit 0 +else + exit 1 +fi diff --git a/modprobe.conf.tar.bz2 b/modprobe.conf.tar.bz2 new file mode 100644 index 0000000..dbae041 --- /dev/null +++ b/modprobe.conf.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ac5daaf81b8c4c6c0aa83b9ffc89aedada1d1e8ff864166ecb52034a628b375 +size 2783 diff --git a/suse-module-tools.changes b/suse-module-tools.changes new file mode 100644 index 0000000..0390252 --- /dev/null +++ b/suse-module-tools.changes @@ -0,0 +1,5 @@ +------------------------------------------------------------------- +Wed Nov 14 18:31:35 UTC 2012 - jengelh@inai.de + +- New package. Split SUSE-specific scripts from module-init-tools, + so that we can actually get a system with kmod-compat running. diff --git a/suse-module-tools.spec b/suse-module-tools.spec new file mode 100644 index 0000000..114c3d8 --- /dev/null +++ b/suse-module-tools.spec @@ -0,0 +1,144 @@ +# +# spec file for package suse-module-tools +# +# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# + + +Name: suse-module-tools +Version: 12.3 +Release: 0 +# for grepping /etc/SUSE-release +PreReq: grep +# nm and rpmsort (rpm) are required by the weak-modules script which is invoked +# in post, it also requires getopt (coreutils) and sed +PreReq: coreutils rpm +# XXX: this should be nm OR eu-nm, the script works with both +PreReq: /usr/bin/eu-nm /bin/sed +Summary: Configuration for module loading and SUSE-specific utilities for KMPs +License: GPL-2.0+ +Group: System/Base +Source: README.SUSE +Source2: modprobe.conf.tar.bz2 +Source3: depmod-00-system.conf +Source4: 10-unsupported-modules.conf +Source5: weak-modules +Source6: weak-modules2 +Source7: driver-check.sh +BuildRoot: %{_tmppath}/%{name}-%{version}-build +BuildArch: noarch + +%description +This package contains helper scripts for KMP installation and +uninstallation, as well as default configuration files for depmod and +modprobe. These utilities are provided by kmod-compat or +module-init-tools, whichever implementation you choose to install. + +%prep +%setup -Tcqa2 + +%build + +%install +b="%buildroot" +mkdir -p "$b/%_docdir/module-init-tools" +install -pm644 "%_sourcedir/README.SUSE" "$b/%_docdir/module-init-tools" +# +# now assemble the parts for modprobe.conf +# +cd modprobe.conf +cp modprobe.conf.common 00-system.conf +if [ -f "modprobe.conf.$RPM_ARCH" ]; then + cat "modprobe.conf.$RPM_ARCH" >>00-system.conf +fi +install -d -m 755 "$b/etc/modprobe.d" +install -pm644 "%_sourcedir/10-unsupported-modules.conf" \ + "$b/etc/modprobe.d/" +install -pm644 00-system.conf "$b/etc/modprobe.d/" +install -pm644 modprobe.conf.local "$b/etc/modprobe.d/99-local.conf" +install -d -m 755 "$b/etc/depmod.d" +install -pm 644 "%_sourcedir/depmod-00-system.conf" \ + "$b/etc/depmod.d/00-system.conf" + +# "module-init-tools" name hardcoded in KMPs, mkinitrd, etc. +install -d -m 755 "$b/usr/lib/module-init-tools" +install -pm 755 %_sourcedir/weak-modules{,2} "$b/usr/lib/module-init-tools/" +install -pm 755 %_sourcedir/driver-check.sh "$b/usr/lib/module-init-tools/" + +%post +test_allow_on_install() +{ + # configure handling of unsupported modules + # default is to allow them + allow=1 + # if the obsolete LOAD_UNSUPPORTED_MODULES_AUTOMATICALLY variable is + # set to no, don't allow (this was used in SLES 9 and 10) + if test -e /etc/sysconfig/hardware/config; then + . /etc/sysconfig/hardware/config + if test "x$LOAD_UNSUPPORTED_MODULES_AUTOMATICALLY" = "xno"; then + allow=0 + fi + # obsolete + rm /etc/sysconfig/hardware/config + fi + # don't change the setting during upgrade + if test "$1" != 1; then + return + fi + # on SLES, the default is not to allow unsupported modules + if grep -qs "Enterprise Server" /etc/SuSE-release; then + allow=0 + else + return + fi + # unless the admin passed "oem-modules=1" to the kernel during install + if grep -qs '\' /proc/cmdline; then + allow=1 + return + fi + # or if the installer already loaded some unsupported modules + # (see TAINT_NO_SUPPORT in /usr/src/linux/include/linux/kernel.h) + tainted=$(cat /proc/sys/kernel/tainted 2>/dev/null || echo 0) + if test $((tainted & (1<<30))) != 0; then + allow=1 + return + fi +} +# upgrade from old locations +if test -e /etc/modprobe.d/unsupported-modules; then + mv -f /etc/modprobe.d/unsupported-modules \ + /etc/modprobe.d/10-unsupported-modules.conf +fi +if test -e /etc/modprobe.conf.local; then + mv -f /etc/modprobe.conf.local \ + /etc/modprobe.d/99-local.conf +fi +test_allow_on_install "$@" +if test "$allow" = "0"; then + sed -ri 's/^( *allow_unsupported_modules *) 1/\1 0/' \ + /etc/modprobe.d/10-unsupported-modules.conf +fi + +%files +%defattr(-,root,root) +%dir /etc/modprobe.d +%config /etc/modprobe.d/00-system.conf +%config(noreplace) /etc/modprobe.d/10-unsupported-modules.conf +%config(noreplace) /etc/modprobe.d/99-local.conf +%dir /etc/depmod.d +%config /etc/depmod.d/00-system.conf +%_docdir/module-init-tools +/usr/lib/module-init-tools + +%changelog diff --git a/weak-modules b/weak-modules new file mode 100644 index 0000000..93888a2 --- /dev/null +++ b/weak-modules @@ -0,0 +1,325 @@ +#! /bin/bash + +# This script is only needed to uninstall old KMPs when updating +# SLE10 to SLE11+. weak-modules2 is the script what should be used by new +# packages + +unset LANG LC_ALL LC_COLLATE + +NM= +if command -v nm >/dev/null; then + NM=nm +elif command -v eu-nm >/dev/null; then + NM=eu-nm +else + echo "ERROR: nm not found" >&2 + exit 1 +fi + +# Check if MODULE is compatible with kernel release KREL. +module_is_compatible() { + declare module=$1 krel=$2 module_krel=$(krel_of_module "$module") + + if [ ! -e $tmpdir/all-symvers-$krel-$module_krel ]; then + # Symbols exported by the "new" kernel + if [ ! -e $tmpdir/symvers-$krel ]; then + if [ -e /boot/symvers-$krel.gz ]; then + zcat /boot/symvers-$krel.gz \ + | sed -r -ne 's:^0x0*([0-9a-f]+\t[0-9a-zA-Z_]+)\t.*:\1:p' + fi > $tmpdir/symvers-$krel + fi + + # Symbols that other add-on modules of the "old" kernel export + # (and that this module may require) + if [ ! -e $tmpdir/extra-symvers-$module_krel ]; then + if [ -e /lib/modules/$module_krel/updates ]; then + find /lib/modules/$module_krel/updates -name '*.ko' \ + | xargs $NM -B \ + | sed -nre 's:^0*([0-9a-f]+) A __crc_(.*):\1 \2:p' + fi > $tmpdir/extra-symvers-$module_krel + fi + + sort -u $tmpdir/symvers-$krel $tmpdir/extra-symvers-$module_krel \ + > $tmpdir/all-symvers-$krel-$module_krel + fi + + # If the module does not have modversions enabled, $tmpdir/modvers + # will be empty. + /sbin/modprobe --dump-modversions "$module" \ + | sed -r -e 's:^0x0*([0-9a-f]+\t.*):\1:' \ + | sort -u \ + > $tmpdir/modvers + + # Only include lines of the second file in the output that don't + # match lines in the first file. (The default separator is + # , so we are matching the whole line.) + join -j 1 -v 2 $tmpdir/all-symvers-$krel-$module_krel \ + $tmpdir/modvers > $tmpdir/join + + if [ ! -s $tmpdir/modvers ]; then + echo "Warning: Module ${module##*/} from kernel $module_krel has no" \ + "modversions, so it cannot be reused for kernel $krel" >&2 + elif [ -s $tmpdir/join ]; then + [ -n "$verbose" ] && + echo "Module ${module##*/} from kernel $module_krel is not compatible" \ + "with kernel $krel in symbols:" $(sed -e 's:.* ::' $tmpdir/join) + elif [ "$krel" != "$module_krel" ]; then + [ -n "$verbose" ] && + echo "Module ${module##*/} from kernel $module_krel is compatible" \ + "with kernel $krel" + return 0 + fi + return 1 +} + +# Compute the kernel release of a module. +krel_of_module() { + declare module=$1 + set -- $(/sbin/modinfo -F vermagic "$module") + echo "$1" +} + +# Read a list of modules from standard input, convert the filenames into +# absolute names, and compute the kernel release of each module. +read_modules_list() { + local saved_IFS=$IFS + IFS=$'\n' + modules=($(cat)) + IFS=$saved_IFS + + for ((n = 0; n < ${#modules[@]}; n++)); do + if [ ${modules[n]:0:1} != / ]; then + modules[n]=$PWD/${modules[n]} + fi + if [ -f "${modules[n]}" ]; then + module_krels[n]=$(krel_of_module "${modules[n]}") + else + # Try to extract the kernel release from the path + set -- "${modules[n]#/lib/modules/}" + module_krels[n]=${1%%/*} + fi + done +} + +doit() { + [ -n "$verbose" ] && echo "$@" + [ -n "$dry_run" ] || "$@" +} + +usage() { + cat <<'EOF' +Usage: ${0##*/} [options] {--add-modules|--remove-modules} + ${0##*/} [options] {--add-kernel|--remove-kernel} {kernel-release} + +--add-modules + Add a list of modules read from standard input. Create + symlinks in compatible kernel's weak-updates/ directory. + The list of modules is read from standard input. + +--remove-modules + Remove compatibility symlinks from weak-updates/ directories + for a list of modules. The list of modules is read from + standard input. + +--add-kernel + Add compatibility symlinks for all compatible modules to the + specified or running kernel. + +--remove-kernel + Remove all compatibility symlinks for the specified or current + kernel. + +--verbose + Print the commands executed. + +-dry-run + Do not create/remove any files. +EOF + exit $1 +} + +[ -e /etc/sysconfig/kernel ] && source /etc/sysconfig/kernel + +unset ${!changed_modules_*} ${!changed_initrd_*} + +module_has_changed() { + declare module=$1 krel=$2 + + module=${module%.ko} + module=${module##*/} + + eval "changed_modules_${krel//[^a-zA-Z0-9]/_}=$krel" + case " $INITRD_MODULES " in + *" $module "*) + eval "changed_initrd_${krel//[^a-zA-Z0-9]/_}=$krel" + ;; + esac +} + +options=`getopt -o h --long help,add-modules,remove-modules \ + --long add-kernel,remove-kernel,dry-run,verbose -- "$@"` + +[ $? -eq 0 ] || usage 1 + +eval set -- "$options" + +while :; do + case "$1" in + --add-modules) + add_modules=1 + ;; + --remove-modules) + remove_modules=1 + ;; + --add-kernel) + add_kernel=1 + ;; + --remove-kernel) + remove_kernel=1 + ;; + --dry-run) + dry_run=1 + ;; + --verbose) + verbose=1 + ;; + -h|--help) + usage 0 + ;; + --) + shift + break + ;; + esac + shift +done + +if [ "$add_modules$remove_modules$add_kernel$remove_kernel" != 1 ]; then + usage 1 +fi +if [ -n "$add_kernel" -o -n "$remove_kernel" ]; then + [ $# -gt 1 ] && usage 1 +else + [ $# -ne 0 ] && usage 1 +fi + +tmpdir=$(mktemp -td ${0##*/}.XXXXXX) +trap "rm -rf $tmpdir" EXIT + +if [ -n "$add_modules" ]; then + read_modules_list || exit 1 + if [ ${#modules[@]} -gt 0 ]; then + for krel in $(ls /lib/modules/); do + [ -e /boot/symvers-$krel.gz ] || continue + for ((n = 0; n < ${#modules[@]}; n++)); do + module=${modules[n]} + module_krel=${module_krels[n]} + case "$module" in + /lib/modules/$krel/*) + continue ;; + esac + subpath=${module#/lib/modules/$module_krel/updates} + weak_module=/lib/modules/$krel/weak-updates/${subpath#/} + if [ -r "$weak_module" ]; then + weak_krel=$(krel_of_module "$weak_module") + if [ "$weak_krel" != "$module_krel" ] && + [ "$(printf "%s\n" "$weak_krel" "$module_krel" \ + | /usr/lib/rpm/rpmsort | head -n 1)" = \ + "$module_krel" ]; then + # Keep modules from more recent kernels. + [ -n "$verbose" ] && echo \ +"Keeping module ${module##*/} from kernel $weak_krel for kernel $krel" + continue + fi + fi + if module_is_compatible $module $krel; then + doit mkdir -p $(dirname $weak_module) + doit ln -sf $module $weak_module + module_has_changed $module $krel + fi + done + done + fi +elif [ -n "$remove_modules" ]; then + read_modules_list || exit 1 + if [ ${#modules[@]} -gt 0 ]; then + krels=($(ls /lib/modules/ | /usr/lib/rpm/rpmsort -r)) + for krel in "${krels[@]}"; do + [ -e /boot/symvers-$krel.gz ] || continue + for ((n = 0; n < ${#modules[@]}; n++)); do + module=${modules[n]} + [ -e "$module" ] && continue + module_krel=${module_krels[n]} + subpath=${module#/lib/modules/$module_krel/updates} + weak_module=/lib/modules/$krel/weak-updates/${subpath#/} + if [ "$(readlink "$weak_module")" = "$module" ]; then + [ -n "$verbose" ] && echo \ +"Removing compatible module ${subpath#/} from kernel $krel" + doit rm -f "$weak_module" + for krel2 in "${krels[@]}"; do + [ -e /boot/symvers-$krel2.gz ] || continue + module=/lib/modules/$krel2/updates/${subpath#/} + [ -e "$module" ] || continue + if module_is_compatible "$module" "$krel2"; then + [ -n "$verbose" ] && echo \ +"Adding compatible module ${module##*/} from kernel $krel2 instead" + doit ln -s "$module" "$weak_module" + break + fi + done + doit rmdir --parents --ignore-fail-on-non-empty \ + "$(dirname "$weak_module")" + module_has_changed $module $krel + fi + done + done + fi +elif [ -n "$add_kernel" ]; then + add_krel=${1:-$(uname -r)} + if [ ! -e /boot/symvers-$add_krel.gz ]; then + echo "Symvers dump file /boot/symvers-$add_krel.gz" \ + "not found" >&2 + exit 1 + fi + for krel in $(ls /lib/modules/ | /usr/lib/rpm/rpmsort -r); do + [ "$add_krel" = "$krel" ] && continue + [ -d /lib/modules/$krel/updates ] || continue + for module in $(find /lib/modules/$krel/updates -name '*.ko'); do + subpath=${module#/lib/modules/$krel/updates} + weak_module=/lib/modules/$add_krel/weak-updates/${subpath#/} + [ -e "$weak_module" ] && continue + if module_is_compatible $module $add_krel; then + doit mkdir -p $(dirname $weak_module) + doit ln -sf $module $weak_module + fi + done + done +elif [ -n "$remove_kernel" ]; then + remove_krel=${1:-$(uname -r)} + weak_modules=/lib/modules/$remove_krel/weak-updates + doit rm -rf "$weak_modules" +fi + +for krel in ${!changed_modules_*}; do + krel=${!krel} + [ -e /boot/System.map-$krel ] || continue + /sbin/depmod -ae -F /boot/System.map-$krel $krel +done + +for krel in ${!changed_initrd_*}; do + krel=${!krel} + [ -e /boot/System.map-$krel ] || continue + + image= + for x in vmlinuz image vmlinux linux bzImage uImage; do + if [ -f /boot/$x-$krel ]; then + image=$x + break + fi + done + if [ -n "$image" ]; then + /sbin/mkinitrd -k /boot/$image-$krel -i /boot/initrd-$krel + fi +done + +# vim:shiftwidth=4 softtabstop=4 diff --git a/weak-modules2 b/weak-modules2 new file mode 100644 index 0000000..ac46c8f --- /dev/null +++ b/weak-modules2 @@ -0,0 +1,684 @@ +#! /bin/bash + +############################################################################## +# How it works: +# * Kernels install modules below /lib/modules/$krel/kernel/. +# * KMPs install modules below /lib/modules/$krel/updates/ or .../extra/. +# * Symbolic links to modules of compatible KMPs are created under +# /lib/modules/$krel/weak-updates/{updates,extra}/... (the original path +# below /lib/modules/$other_krel is used). +# * Depmod searches the directories in this order: updates/, extra/, +# weak-updates/, kernel/ (see /etd/depmod.conf or +# /etc/depmod.d/00-system.conf for details). +# * Compatibility of a kernel with a KMP is defined as: The KMP is built +# for the same flavor as the kernel and after adding the KMP modules to +# the kernel, depmod -e -E Module.symvers reports no errors about +# missing symbols or different symbol checksums. See the +# has_unresolved_symbols() function for details. +# +# * At KMP install time (function add_kmp()), we create symbolic links +# for all kernels that this KMP is compatible with. We skip kernels that +# already contain symbolic links to a newer KMP of the same name, +# contain the KMP itself or another version in updates/ or extra/ or +# have overlapping module names with other KMPs in the respective +# kernel (this should not happen). +# * At kernel install time (functions add_kernel()), we create symbolic +# links for each compatible KMP, unless the KMP or a different one with +# overlapping module names is present in updates/ or extra/ (KMP build +# against $krel can be installed before a kernel with that version). +# When multiple KMPs of the same name are compatbile, we chose the one +# with the highest version number. This is repeated when subsequent +# subpackages (main or -extra) of that kernel are installed. +# * At KMP removal time (function remove_kmp()), the modules and their +# symlinks are removed and, where possible, replaced by symlinks to the +# newest of the remaining compatible version of that KMP. +# * [NOT IMPLEMENTED] When a kernel subpackage is removed, symlinks to +# KMPs that become incompatible are removed as well. This is not +# implemented, because removing the main subpackage and only keeping +# the -base package AND having KMPs installed is not an expected +# scenario, and implementing this would only slow down kernel updates. +# * When the kernel is removed (function remove_kernel()), it's +# weak-updates directory is also removed. +# +# naming conventions used in this script: +# $kmp: name-version-release of a kmp, e.g kqemu-kmp-default-1.3.0pre11_2.6.25.16_0.1-7.1 +# $kmpshort: name of a kmp, e.g kqemu-kmp-default +# $basename: portion of $kmp up to the "-kmp-" part, e.g kqemu +# $flavor: flavor of a kmp or kernel, e.g default +# $krel: kernel version, as in /lib/modules/$krel +# $module: full path to a module below updates/ +# $symlink: full path to a module symlink below weak-updates/ +# +# files in $tmpdir: +# krel-$kmp: kernel version for which $kmp was built +# modules-$kmp: list of modules in $kmp (full paths) +# basenames-$kmp: list of basenames of modules in $kmp +# kmps: list of kmps, newest first +# + +log() { + [ -n "$opt_verbose" ] && echo "$@" >&2 +} + +doit() { + if [ -n "$doit" ]; then + # override + "$@" + return + fi + log "$@" + if [ -z "$opt_dry_run" ]; then + "$@" + else + : + fi +} + +filter_basenames() { + sed -rn 's:/?lib/modules/.*/([^/]*\.ko)$:\1:p' +} + +# Name of the symlink that makes a module available to a given kernel +symlink_to_module() { + local module=$1 krel=$2 + + echo /lib/modules/$krel/weak-updates/${module#/lib/modules/*/} +} + +# Is a kmp already present in or linked to from this kernel? +kmp_is_present() { + local kmp=$1 krel=$2 + + if [ $krel = "$(cat $tmpdir/krel-$kmp)" ]; then + return 0 + fi + local module symlink + while read module; do + symlink=$(symlink_to_module $module $krel) + [ $module -ef $symlink -o $module = "$(readlink $symlink)" ] || return 1 + done < $tmpdir/modules-$kmp + + return 0 +} + +# Add the modules of a kmp to /lib/modules/$krel +add_kmp_modules() { + local kmp=$1 krel=$2 basedir=$3 + + [ -n "$kmp" ] || return 0 + + local module symlink + while read module; do + symlink=$(symlink_to_module $module $krel) + doit mkdir -p ${opt_debug:+-v} $basedir${symlink%/*} || exit 1 + doit ln -sf ${opt_debug:+-v} $module $basedir$symlink || exit 1 + done < $tmpdir/modules-$kmp +} + +# Remove the modules of a kmp from /lib/modules/$krel +remove_kmp_modules() { + local kmp=$1 krel=$2 basedir=$3 + + [ -n "$kmp" ] || return 0 + + local module symlink + while read module; do + symlink=$(symlink_to_module $module $krel) + doit rm -f ${opt_debug:+-v} $basedir$symlink + done < $tmpdir/modules-$kmp +} + +# Create a temporary working copy of /lib/modules/$1 +create_temporary_modules_dir() { + local modules_dir=/lib/modules/$1 basedir=$2 + local opt_v=${opt_debug:+-v} + + mkdir -p $opt_v $basedir$modules_dir/weak-updates + ln -s $opt_v $modules_dir/kernel $basedir$modules_dir/kernel + + eval "$(find $modules_dir -path "$modules_dir/modules.*" -prune \ + -o -path "$modules_dir/kernel" -prune \ + -o -type d -printf "mkdir -p $opt_v $basedir%p\n" \ + -o -printf "ln -s $opt_v %p $basedir%p\n" + )" +} + +# Check for unresolved symbols +has_unresolved_symbols() { + local krel=$1 basedir=$2 output status args sym_errors + + if [ ! -e $tmpdir/symvers-$krel -a -e /boot/symvers-$krel.gz ]; then + zcat /boot/symvers-$krel.gz > $tmpdir/symvers-$krel + fi + if [ -e $tmpdir/symvers-$krel ]; then + args=(-E $tmpdir/symvers-$krel) + else + echo "warning: $tmpdir/symvers-$krel not available" >&2 + args=(-F /boot/System.map-$krel) + fi + output="$(/sbin/depmod -b "$basedir" -ae "${args[@]}" $krel 2>&1)" + status=$? + if [ $status -ne 0 ]; then + echo "$output" >&2 + echo "depmod exited with error $status" >&2 + return 0 + fi + sym_errors=$(echo "$output" | \ + grep -E ' (needs unknown|disagrees about version of) symbol ') + if [ -n "$sym_errors" ]; then + [ -z "$opt_debug" ] || echo "$sym_errors" >&2 + return 0 + fi + + return 1 +} + +# KMPs can only be added if none of the module basenames overlap +basenames_are_unique() { + local kmp=$1 krel=$2 basedir=$3 dir + + for dir in $basedir/lib/modules/$krel/{weak-updates,updates,extra}/; do + if [ ! -d "$dir" ]; then + continue + fi + if [ -n "$(comm -1 -2 $tmpdir/basenames-$kmp \ + <(find "$dir" -not -type d -printf '%f\n' | sort -u))" ]; then + return 1 + fi + done + return 0 +} + +# Can a kmp be replaced by a different version of the same kmp in a kernel? +# Set the old kmp to "" when no kmp is to be removed. +can_replace_kmp() { + local old_kmp=$1 new_kmp=$2 krel=$3 + + local basedir=$tmpdir/$krel + local weak_updates=/lib/modules/$krel/weak-updates/ + + [ -d "$basedir" ] || \ + create_temporary_modules_dir "$krel" "$basedir" + + # force doit() to execute the commands (in $tmpdir) + doit=1 remove_kmp_modules "$old_kmp" "$krel" "$basedir" + if ! basenames_are_unique "$new_kmp" "$krel" "$basedir"; then + doit=1 add_kmp_modules "$old_kmp" "$krel" "$basedir" + return 1 + fi + doit=1 add_kmp_modules "$new_kmp" "$krel" "$basedir" + if has_unresolved_symbols "$krel" "$basedir"; then + doit=1 remove_kmp_modules "$new_kmp" "$krel" "$basedir" + doit=1 add_kmp_modules "$old_kmp" "$krel" "$basedir" + return 1 + fi + return 0 +} + +# Figure out which modules a kmp contains +check_kmp() { + local kmp=$1 + + # Make sure all modules are for the same kernel + set -- $(sed -re 's:^/lib/modules/([^/]+)/.*:\1:' \ + $tmpdir/modules-$kmp \ + | sort -u) + if [ $# -ne 1 ]; then + echo "Error: package $kmp seems to contain modules for multiple" \ + "kernel versions" >&2 + return 1 + fi + echo $1 > $tmpdir/krel-$kmp + + # Make sure none of the modules are in kernel/ or weak-updates/ + if grep -qE -e '^/lib/modules/[^/]+/(kernel|weak-updates)/' \ + $tmpdir/modules-$kmp; then + echo "Error: package $kmp must not install modules into " \ + "kernel/ or weak-updates/" >&2 + return 1 + fi + sed -e 's:.*/::' $tmpdir/modules-$kmp \ + | sort -u > $tmpdir/basenames-$kmp +} + +# Figure out which kmps there are, and which modules they contain +# set basename to '*' to find all kmps of a given flavor +find_kmps() { + local basename=$1 flavor=$2 + local kmp + + for kmp in $(rpm -qa --qf '%{n}-%{v}-%{r}\n' --nodigest --nosignature "$basename-kmp-$flavor"); do + rpm -ql --nodigest --nosignature "$kmp" \ + | grep -Ee '^/lib/modules/[^/]+/.+\.ko$' \ + > $tmpdir/modules-$kmp + if [ $? != 0 ]; then + echo "WARNING: $kmp does not contain any kernel modules" >&2 + rm -f $tmpdir/modules-$kmp + continue + fi + + check_kmp $kmp || return 1 + done + + printf "%s\n" $tmpdir/basenames-* \ + | sed -re "s:$tmpdir/basenames-::" \ + | /usr/lib/rpm/rpmsort -r \ + > $tmpdir/kmps +} + +previous_version_of_kmp() { + local new_kmp=$1 krel=$2 + local module symlink old_kmp + + while read module; do + symlink=$(symlink_to_module $module $krel) + [ -e "$symlink" ] || continue + [ -L "$symlink" ] || return + + old_kmp=$(grep -l "$(readlink "$symlink")" $tmpdir/modules-* | sed 's:.*/modules-::' ) || return + # The package %NAME must be the same + [ "${old_kmp%-*-*}" == "${new_kmp%-*-*}" ] || return + # The other kmp must be older + while read kmp; do + [ "$kmp" == "$old_kmp" ] && return + [ "$kmp" == "$new_kmp" ] && break + done <$tmpdir/kmps + done < $tmpdir/modules-$new_kmp + echo "$old_kmp" +} + +# test if mkinitrd is needed for $krel. This should be decided by initrd itself +# actually +# stdin - list of changed modules ("_kernel_" for the whole kernel) +needs_mkinitrd() { + local krel=$1 + local changed_basenames=($(sort -u)) + + # Don't generate an initrd for kdump here. It's done automatically with mkdumprd when + # /etc/init.d/boot.kdump is called to load the kdump kernel. See mkdumprd(8) why + # it is done this way. + if [[ "$krel" == *kdump* ]] ; then + return 1 + fi + + if ! [ -f /etc/fstab -a ! -e /.buildenv -a -x /sbin/mkinitrd ] ; then + echo "Please run mkinitrd as soon as your system is complete." >&2 + return 1 + fi + # KMPs can force mkinitrd run with %kernel_module_package -b that sets + # this variable + if test -n "$KMP_NEEDS_MKINITRD" && \ + ! test "$KMP_NEEDS_MKINITRD" -eq 0 2>/dev/null; then + return 0 + fi + if [ "$changed_basenames" = "_kernel_" ]; then + return 0 + fi + if [ ! -e /boot/initrd-$krel ]; then + return 0 + fi + local initrd_basenames=($( (gzip -cd /boot/initrd-$krel | cpio -t --quiet | filter_basenames; INITRD_MODULES=; . /etc/sysconfig/kernel &>/dev/null; printf '%s.ko\n' $INITRD_MODULES) | sort -u)) + local i=($(join <(printf '%s\n' "${changed_basenames[@]}") \ + <(printf '%s\n' "${initrd_basenames[@]}") )) + log "changed initrd modules for kernel $krel: ${i[@]-none}" + if [ ${#i[@]} -gt 0 ]; then + return 0 + fi + return 1 +} + +# run depmod and mkinitrd for kernel version $krel +# stdin - list of changed modules ("_kernel_" for a whole kernel) +run_depmod_and_mkinitrd() { + local krel=$1 + local status=0 + + if [ -d /lib/modules/$krel -a -f /boot/System.map-$krel ] ; then + doit /sbin/depmod -F /boot/System.map-$krel -ae $krel || return 1 + fi + if needs_mkinitrd $krel; then + local image + for x in vmlinuz image vmlinux linux bzImage uImage; do + if [ -f /boot/$x-$krel ]; then + image=$x + break + fi + done + if [ -n "$image" ]; then + doit /sbin/mkinitrd -k /boot/$image-$krel -i /boot/initrd-$krel + status=$? + # mkinitrd fails with status 10 if any required kernel modules + # missing. We expect those modules to be added later (by one of + # the other kernel-$flavor packages). + if [ $status -eq 10 ]; then + log "mkinitrd failed with status 10 (module missing), proceeding" + status=0 + fi + else + echo "WARNING: kernel image for $krel not found!" >&2 + fi + fi + return $status +} + +kernel_changed() { + local krel=$1 flavor=${1##*-} + + if [ ! -f /boot/System.map-$krel ]; then + # this kernel does not exist anymore + return 0 + fi + if [ ! -d /lib/modules/$krel ]; then + # a kernel without modules - run mkinitrd nevertheless (to mount the + # root fs, etc). + echo "_kernel_" | run_depmod_and_mkinitrd "$krel" + return + fi + + find_kmps '*' $flavor || return 1 + local kmps=( $(cat $tmpdir/kmps) ) + + while :; do + [ ${#kmps[@]} -gt 0 ] || break + local added='' skipped='' n kmp + for ((n=0; n<${#kmps[@]}; n++)); do + kmp=${kmps[n]} + [ -n "$kmp" ] || continue + + if kmp_is_present $kmp $krel; then + log "Package $kmp does not need to be added to kernel $krel" + kmps[n]='' + continue + fi + local old_kmp=$(previous_version_of_kmp $kmp $krel) + if can_replace_kmp "$old_kmp" $kmp $krel; then + remove_kmp_modules "$old_kmp" "$krel" + add_kmp_modules "$kmp" "$krel" + if [ -z "$old_kmp" ]; then + log "Package $kmp added to kernel $krel" + else + log "Package $old_kmp replaced by package $kmp in kernel $krel" + fi + added=1 + kmps[n]='' + continue + fi + skipped=1 + done + [ -n "$added" -a -n "$skipped" ] || break + done + echo "_kernel_" | run_depmod_and_mkinitrd "$krel" +} + +add_kernel() { + local krel=$1 + + kernel_changed $krel +} + +remove_kernel() { + local krel=$1 + + local dir=/lib/modules/$krel + if [ -d $dir/weak-updates ]; then + rm -rf $dir/weak-updates + fi + # If there are no KMPs left, remove the empty directory + rmdir $dir 2>/dev/null +} + +add_kernel_modules() { + local krel=$1 + cat >/dev/null + + kernel_changed $krel +} + +remove_kernel_modules() { + local krel=$1 + cat >/dev/null + + # FIXME: remove KMP symlinks that no longer work + kernel_changed $krel +} + +add_kmp() { + local kmp=$1 kmpshort=${1%-*-*} + local basename=${kmpshort%-kmp-*} flavor=${kmpshort##*-} + + # Find the kmp to be added as well as any previous versions + find_kmps "$basename" "$flavor" || return 1 + + local dir krel status + for dir in /lib/modules/*; do + krel=${dir#/lib/modules/} + case "$krel" in + *-$flavor) + ;; + *) + continue + esac + [ -d $dir -a -f /boot/System.map-$krel ] || continue + if opt_debug=1 has_unresolved_symbols "$krel" "/"; then + echo "Warning: /lib/modules/$krel is inconsistent" >&2 + echo "Warning: weak-updates symlinks might not be created" >&2 + fi + + if kmp_is_present $kmp $krel; then + log "Package $kmp does not need to be added to kernel $krel" + run_depmod_and_mkinitrd "$krel" <$tmpdir/basenames-$kmp || \ + status=1 + continue + fi + local old_kmp=$(previous_version_of_kmp $kmp $krel) + if can_replace_kmp "$old_kmp" $kmp $krel; then + remove_kmp_modules "$old_kmp" "$krel" + add_kmp_modules "$kmp" "$krel" + if [ -z "$old_kmp" ]; then + log "Package $kmp added to kernel $krel" + run_depmod_and_mkinitrd "$krel" <$tmpdir/basenames-$kmp || \ + status=1 + else + log "Package $old_kmp replaced by package $kmp in kernel $krel" + cat $tmpdir/basenames-{$old_kmp,$kmp} \ + | run_depmod_and_mkinitrd "$krel" || status=1 + fi + fi + done + return $status +} + +remove_kmp() { + local kmp=$1 kmpshort=${1%-*-*} + local basename=${kmpshort%-kmp-*} flavor=${kmpshort##*-} + + # Find any previous versions of the same kmp + find_kmps "$basename" "$flavor" || return 1 + + # Read the list of module names from standard input + # (This kmp may already have been removed!) + cat > $tmpdir/modules-$kmp + check_kmp "$kmp" || return 1 + + local dir krel status + for dir in /lib/modules/*; do + krel=${dir#/lib/modules/} + case "$krel" in + *-$flavor) + ;; + *) + continue + esac + [ -d $dir -a -f /boot/System.map-$krel ] || continue + if opt_debug=1 has_unresolved_symbols "$krel" "/"; then + echo "Warning: /lib/modules/$krel is inconsistent" >&2 + echo "Warning: weak-updates symlinks might not be created" >&2 + fi + if kmp_is_present $kmp $krel; then + if [ $krel != "$(cat $tmpdir/krel-$kmp)" ]; then + remove_kmp_modules "$kmp" "$krel" + fi + + local other_kmp + while read other_kmp; do + [ "$kmp" != "$other_kmp" ] || continue + + if can_replace_kmp "" "$other_kmp" "$krel"; then + add_kmp_modules "$other_kmp" "$krel" + break + fi + done < $tmpdir/kmps + if [ -n "$other_kmp" ]; then + log "Package $kmp replaced by package $other_kmp in kernel $krel" + cat $tmpdir/basenames-{$kmp,$other_kmp} \ + | run_depmod_and_mkinitrd "$krel" || status=1 + else + log "Package $kmp removed from kernel $krel" + run_depmod_and_mkinitrd "$krel" <$tmpdir/basenames-$kmp || \ + status=1 + fi + fi + done + return $status +} + +help() { +cat <&2 + exit 1 +fi +eval set -- "$options" +mode= +while :; do + case "$1" in + --add-kernel | --remove-kernel | --add-kernel-modules | \ + --remove-kernel-modules | --add-kmp | --remove-kmp ) + mode="$1" + ;; + -v | --verbose) + opt_verbose=1 + ;; + --dry-run) + opt_dry_run=1 + ;; + --debug) + opt_debug=1 + ;; + --usage) + usage + exit 0 + ;; + -h | --help) + help + exit 0 + ;; + --) + shift + break + ;; + esac + shift +done + +err= +case "$mode" in +"") + err="Please specify one of the --add-* or --remove-* options" + ;; +--add-kernel | --remove-kernel) + if [ $# -gt 1 ]; then + err="Too many arguments to $mode" + fi + [ $# -eq 1 ] || set -- $(uname -r) + ;; +*) + if [ $# -ne 1 ]; then + err="Option $mode requires exactly one argument" + fi + ;; +esac +if [ -n "$err" ]; then + echo "ERROR: $err" >&2 + usage >&2 + exit 1 +fi + +#unset LANG LC_ALL LC_COLLATE + +tmpdir=$(mktemp -d /var/tmp/${0##*/}.XXXXXX) +trap "rm -rf $tmpdir" EXIT + +shopt -s nullglob + +case $mode in +--add-kernel) + add_kernel "$1" + ;; +--remove-kernel) + remove_kernel "$1" + ;; +--add-kernel-modules) + add_kernel_modules "$1" + ;; +--remove-kernel-modules) + remove_kernel_modules "$1" + ;; +--add-kmp) + add_kmp "$1" + ;; +--remove-kmp) + remove_kmp "$1" +esac + +# vim:shiftwidth=4 softtabstop=4