#!/bin/bash # vim:ts=4 # Distributed under the terms of the GNU General Public License v2 # # This script will do: # - create /etc/modules.conf from /etc/modules.d/* # - create /etc/modprobe.conf from /etc/modprobe.d/* # - update modules.dep if modules.conf has been updated so depmod doesnt whine # # This is all for backwards compatibility. In the perfect world, we would be # running a linux-2.6 kernel and not have any modules.d directory. Then there # would be no work for us as module-init-tools automatically scans modprobe.d. # Until that happens, we'll keep scanning and warning and being a pita. # ROOT="${ROOT%/}/" [ "${ROOT}" = "${ROOT#/}" ] && ROOT="${PWD}/${ROOT}" cd "${ROOT}" argv0=${0##*/} . /etc/init.d/functions.sh || { echo "${argv0}: Could not source /etc/init.d/functions.sh!" 1>&2 exit 1 } umask 022 esyslog() { :; } export PATH=/sbin:${PATH} [ "${argv0}" = "modules-update" ] && ewarn "Please run 'update-modules' from now on; 'modules-update' is going away" # # Setup some variables # HEADER="### This file is automatically generated by update-modules" # # Parse command-line # VERBOSE=0 DEBUG=0 FORCE="false" BACKUP="false" KV= while [ -n "$1" ] ; do case $1 in --assume-kernel=*) KV=${1#*=};; -b|--backup) BACKUP="true";; -f|--force|force) FORCE="true";; -v|--verbose) ((VERBOSE+=1));; -d|--debug) ((DEBUG+=1));; -V|--version) exec echo "${argv0}$Revision: 1.1 $ $Date: 2008/10/25 23:55:43 $";; -h|--help) cat <<-EOF Usage: update-modules [options] Options: --assume-kernel=KV Assume the kernel is at least version KV -b, --backup Backup existing config files (add .old ext) -f, --force Force execution in face of bad things -v, --verbose Be a bit more verbose in what we do -d, --debug Helpful debug output -V, --version Dump version info -h, --help This help screen, duh EOF exit 0 ;; *) eerror "Error: I don't understand $1" exit 1 ;; esac shift done if [ ! -w ./etc ] ; then eerror "You must be root to do this" exit 2 fi [ ${DEBUG} -gt 0 ] && set -x veinfo() { [ ${VERBOSE} -gt 0 ] && einfo "$*" ; return 0 ; } vewarn() { [ ${VERBOSE} -gt 0 ] && ewarn "$*" ; return 0 ; } [ "${ROOT}" != "/" ] && veinfo "Operating on ROOT = '${ROOT}'" # # Let's check the optimal case first: nothing to do # if ! ${FORCE} ; then if [ ! -d "./etc/modules.d" ] ; then if [ ! -d "./etc/modprobe.d" ] ; then veinfo "No /etc/modules.d or /etc/modprobe.d dir; Nothing to do!" exit 0 elif [ -e "./etc/modprobe.conf" ] ; then vewarn "You should put settings in /etc/modprobe.d/ rather than modprobe.conf" elif [ -e "./etc/modules.conf" ] ; then vewarn "If you only run linux-2.4, you should delete /etc/modules.conf" else veinfo "We have just /etc/modprobe.d; Nothing to do!" exit 0 fi else vewarn "You have /etc/modules.d, so things need to get coalesced" fi fi # # Build list of config files to generate and verify none # have been modified in any way # for x in modprobe.conf modules.conf ; do x="./etc/${x}" [ -r ${x} ] || continue if [ "$(sed -ne 1p ${x})" != "${HEADER}" ] ; then ewarn "Warning: ${x#.} has not been automatically generated" if ${FORCE} ; then ewarn "--force specified, (re)generating file anyway" else eerror "Use \"update-modules force\" to force (re)generation" exit 1 fi fi done # # If the system doesnt have old modutils, then this is prob linux-2.6 only # if type -P modprobe.old > /dev/null || \ LC_ALL=C modprobe -V 2>/dev/null | grep -qs "modprobe version" then GENERATE_OLD="true" else GENERATE_OLD="false" fi # Reset the sorting order since we depend on it export LC_COLLATE="C" KV=${KV:-$(uname -r)} # # Desc: backup a config file if need be and replace with new one # Usage: backup # Ex: backup /etc/modules.conf /etc/modules.conf.tempfile # backup() { if ${BACKUP} && [ -e "$1" ] ; then mv -f "$1" "$1".old fi mv -f "$2" "$1" } # # Desc: Create module header # Usage: create_header # Ex: create_header /etc/modules.d create_header() { local moddir=$1 cat <<-EOF ${HEADER} # # Please do not edit this file directly. If you want to change or add # anything please take a look at the files in ${moddir} and read # the manpage for update-modules(8). # EOF } # # Desc: Combine all config files in a dir and place output in a file # Usage: generate_config # Ex: generate_config /etc/modules.conf /etc/modules.d # generate_config() { local config=$1 local moddir=$2 local refdir=$3 local silent=$4 local tmpfile="${config}.$$" [ -z "${silent}" ] && ebegin "Updating ${config#./etc/}" create_header ${refdir:-${moddir}} > "${tmpfile}" for cfg in "${moddir}"/* ; do [ -d "${cfg}" ] && continue [ ! -r "${cfg}" ] && continue # Skip backup and RCS files #20597 case ${cfg} in *~|*.bak|*,v) continue;; esac # If config file is found in the reference dir, then skip it [ -n "${refdir}" ] && [ -e "${refdir}/${cfg##*/}" ] && continue ( echo "### update-modules: start processing ${cfg#.}" if [ -x "${cfg}" ] ; then # $cfg can be executable; nice touch, Wichert! :) "${cfg}" else cat "${cfg}" fi echo echo "### update-modules: end processing ${cfg#.}" echo ) >> "${tmpfile}" done backup "${config}" "${tmpfile}" [ -z "${silent}" ] && eend 0 return 0 } # # Generate the old modules.conf file based upon all the snippets in # modules.d. Since modprobe doesnt handle modules.d, we need to gather # the files together in modules.conf for it. # if [ ! -d "./etc/modules.d" ] ; then veinfo "No need to generate modules.conf :)" elif ${FORCE} || is_older_than ./etc/modules.conf ./etc/modules.d ; then generate_config ./etc/modules.conf ./etc/modules.d else veinfo "modules.conf: already up-to-date wheatness" fi # # Call depmod to keep insmod from complaining that modules.conf is more # recent then the modules.dep file. # if [ -e "./etc/modules.conf" ] ; then depfile=$( # the modules.conf file has optional syntax: # depfile=/path/to/modules.dep ret=$(sed -n -e '/^[[:space:]]*depfile=/s:.*=::p' ./etc/modules.conf) eval echo "${ret:-/lib/modules/${KV}/modules.dep}" ) if [ -d "${depfile%/*}" ] ; then if [ ./etc/modules.conf -nt "${depfile}" ] ; then arch=$(uname -m) ebegin "Updating modules.dep" for cfg in /lib/modules/${KV}/build /usr/src/linux-${KV} \ /lib/modules/${KV} /boot /usr/src/linux "" do cfg=".${cfg}/System.map" for suffix in -genkernel-${arch}-${KV} -genkernel-'*'-${KV} -${KV} "" ; do scfg=$(echo ${cfg}${suffix}) scfg=${scfg%% *} [ -f "${scfg}" ] && cfg=${scfg} && break 2 done cfg="" done [ -n "${cfg}" ] && cfg="-F ${cfg}" depmod -b "${ROOT}" -a ${cfg} ${KV} eend $? veinfo "Ran: depmod -b '${ROOT}' -a ${cfg} ${KV}" else veinfo "modules.dep: already up-to-date goodness" fi else vewarn "The dir '${depfile}' does not exist, skipping call to depmod" fi fi # # Generate the new modprobe.conf file if possible. What this entails is # grabbing details from the old modprobe via the -c option and sticking # it in the newer config file. This is useful for backwards compat support # and for packages that provide older style /etc/modules.d/ files but not # newer style /etc/modprobe.d/ files. # # First we try to use the script `generate-modprobe.conf` from the # module-init-tools and if that fails us, we try and generate modprobe.conf # ourselves from the /etc/modules.d/ files. # if ! type -P generate-modprobe.conf > /dev/null ; then vewarn "Skipping /etc/modprobe.conf generation (generate-modprobe.conf doesn't exist)" elif ! ${FORCE} && ! is_older_than ./etc/modprobe.conf ./etc/modules.d ./etc/modprobe.d ; then veinfo "modprobe.conf: already up-to-date nutness" elif [ ! -e ./etc/modules.conf -a ! -e ./etc/modules.d ] ; then veinfo "No need to generate modprobe.conf :)" rm -f ./etc/modprobe.conf else # # First, bitch like crazy # for f in ./etc/modules.d/* ; do # hack: ignore baselayout ;x case ${f##*/} in aliases|i386) continue;; esac [ -e "${f}" ] || continue if [ ! -e "./etc/modprobe.d/${f##*/}" ] ; then ewarn "Please file a bug about ${f#.}: it needs an /etc/modprobe.d/${f##*/}" fi done generated_ok=0 tmpfile="./etc/modprobe.conf.$$" # # First we try to use regular generate-modprobe.conf # if ${GENERATE_OLD} ; then ebegin "Updating modprobe.conf" create_header /etc/modprobe.d > "${tmpfile}" if generate-modprobe.conf ${ASSUME_KV:+--assume-kernel=${KV}} \ >> "${tmpfile}" 2> "${tmpfile}.err" then backup "./etc/modprobe.conf" "${tmpfile}" eend 0 generated_ok=1 else [[ ${VERBOSE} -gt 0 ]] && cat "${tmpfile}.err" eend 1 "Warning: could not generate /etc/modprobe.conf!" fi fi # # If the helper script failed, we fall back to doing it by hand # if [[ ${generated_ok} -eq 0 ]] ; then ebegin "Updating modprobe.conf by hand" generate_config ./etc/modprobe.conf ./etc/modules.d ./etc/modprobe.d 0 create_header /etc/modprobe.d > "${tmpfile}" # Just use generate-modprobe.conf to filter compatible syntax if TESTING_MODPROBE_CONF=./etc/modprobe.conf \ generate-modprobe.conf ${ASSUME_KV:+--assume-kernel=${KV}} \ >> "${tmpfile}" 2> "${tmpfile}.err" then # we use mv here instead of backup_config() as the call to # generate_config() above already took care of the backup mv -f "${tmpfile}" "./etc/modprobe.conf" eend $? else [[ ${VERBOSE} -gt 0 ]] && cat "${tmpfile}.err" eend 1 "Warning: could not generate /etc/modprobe.conf!" fi fi # # Now append all the new files ... modprobe will not scan /etc/modprobe.d/ # if /etc/modprobe.conf exists, so we need to append /etc/modprobe.conf with # /etc/modprobe.d/* ... http://bugs.gentoo.org/145962 # if [[ -e ./etc/modprobe.conf ]] ; then for cfg in ./etc/modprobe.d/* ; do [ -d "${cfg}" ] && continue [ ! -r "${cfg}" ] && continue # Skip backup and RCS files #20597 case ${cfg} in *~|*.bak|*,v) continue;; esac ( echo echo "### update-modules: start processing ${cfg#.}" cat "${cfg}" echo "### update-modules: end processing ${cfg#.}" ) >> "./etc/modprobe.conf" done fi rm -f "${tmpfile}" "${tmpfile}.err" fi : # make sure we fall through with 0 exit status