#!/bin/bash # vim:ts=4 # # update-modules script originally based on Debian's version. # This script will update all the fun config files in /etc for # kernel modules. # # For 2.4 (and older) kernels we have: # /etc/modules.conf # /etc/modules.d/ # /etc/modules.devfs # # For 2.6+ kernels we have: # /etc/modprobe.conf # /etc/modprobe.d/ # /etc/modprobe.devfs argv0=${0##*/} source /etc/init.d/functions.sh || { echo "${argv0}: Could not source /etc/init.d/functions.sh!" 1>&2 exit 1 } umask 022 esyslog() { :; } if [[ ${EUID} != "0" ]] ; then eerror "You must be root to do this" 1>&2 exit 2 fi [[ ${argv0} == "modules-update" ]] && ewarn "Please run 'update-modules' from now on; 'modules-update' is going away" # # Setup some variables # CFG_OLD_FILE="/etc/modules.conf" CFG_OLD_DIR="/etc/modules.d" CFG_OLD_DEVFS="/etc/modules.devfs" CFG_NEW_FILE="/etc/modprobe.conf" CFG_NEW_DIR="/etc/modprobe.d" CFG_NEW_DEVFS="/etc/modprobe.devfs" HEADER="### This file is automatically generated by update-modules" FULLHEADER="${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). # " # # Parse command-line # VERBOSE=0 DEBUG=0 FORCE="false" BACKUP="false" GENERATE_DEVFS="false" ASSUME_KV= while [[ -n $1 ]] ; do case $1 in -f|--force|force) FORCE="true";; -b|--backup) BACKUP="true";; -D|--devfs) GENERATE_DEVFS="true";; --assume-kernel=*) ASSUME_KV=${1#*=};; -v|--verbose) ((++VERBOSE));; -d|--debug) ((++DEBUG));; -V|--version) exec cat /etc/gentoo-release;; -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 -D, --devfs Force generation of devfs config files -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 [[ ${DEBUG} -gt 0 ]] && set -x vewarn() { [[ ${VERBOSE} -gt 0 ]] && ewarn "$*" ; return 0 ; } if ! ${GENERATE_DEVFS} && [[ -d /etc/devfs.d ]] ; then GENERATE_DEVFS="true" fi if type -p modprobe.old > /dev/null || \ [[ $(modprobe -V 2>/dev/null) == "modprobe version"* ]] then GENERATE_OLD="true" else GENERATE_OLD="false" fi # Set kernel version, either from --assume-kernel or uname -r KV=${ASSUME_KV:-$(uname -r)} if [[ $(KV_to_int ${KV}) -ge "$(KV_to_int 2.5.48)" ]] ; then KERNEL_2_6="true" else KERNEL_2_6="false" fi # Reset the sorting order since we depend on it export LC_ALL="C" # # Build list of config files to generate and verify none # have been modified in any way # CFGFILES="" if ${GENERATE_OLD} ; then CFGFILES="${CFGFILES} ${CFG_OLD_FILE}" ${GENERATE_DEVFS} && CFGFILES="${CFGFILES} ${CFG_OLD_DEVFS}" fi if ${KERNEL_2_6} ; then CFGFILES="${CFGFILES} ${CFG_NEW_FILE}" ${GENERATE_DEVFS} && CFGFILES="${CFGFILES} ${CFG_NEW_DEVFS}" fi for x in ${CFGFILES} ; do [[ -r ${x} ]] || continue if [[ $(sed -ne 1p "${x}") != "${HEADER}" ]] ; then ewarn "Warning: the current ${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 # # 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: 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}" echo "${FULLHEADER//@MODDIR@/${refdir:-${moddir}}}" > "${tmpfile}" for cfg in "${moddir}"/* ; do [[ -d ${cfg} ]] && continue [[ ! -r ${cfg} ]] && continue # Skip backup and RCS files; fixes bug 20597 (07 May 2004 agriffis) [[ ${cfg} == *~ || ${cfg} == *.bak || ${cfg} == *,v ]] && continue # If config file is found in the reference dir, then skip it [[ -n ${refdir} ]] && [[ -e ${refdir}/${cfg##*/} ]] && continue echo "### update-modules: start processing ${cfg}" >> "${tmpfile}" if [[ -x ${cfg} ]] ; then # $cfg can be executable; nice touch, Wichert! :) "${cfg}" >> "${tmpfile}" else cat "${cfg}" >> "${tmpfile}" fi echo >> "${tmpfile}" echo "### update-modules: end processing ${cfg}" >> "${tmpfile}" 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 ${CFG_OLD_DIR} ]] ; then vewarn "Skipping ${CFG_OLD_FILE} generation (${CFG_OLD_DIR} doesn't exist)" elif ! ${GENERATE_OLD} ; then vewarn "Skipping ${CFG_OLD_FILE} generation (prerequisites not satisfied)" elif ! ( ${FORCE} || \ [[ ! -e ${CFG_OLD_FILE} ]] || \ is_older_than ${CFG_OLD_FILE} ${CFG_OLD_DIR} ) then vewarn "Skipping ${CFG_OLD_FILE} generation (file is newer than dependencies)" else generate_config ${CFG_OLD_FILE} ${CFG_OLD_DIR} 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 ! ${KERNEL_2_6} ; then vewarn "Skipping ${CFG_NEW_FILE} generation (not needed for 2.4 kernels)" elif ! type -p generate-modprobe.conf > /dev/null ; then vewarn "Skipping ${CFG_NEW_FILE} generation (generate-modprobe.conf doesn't exist)" elif ! ( ${FORCE} || \ [[ ! -e ${CFG_NEW_FILE} ]] || \ is_older_than ${CFG_NEW_FILE} ${CFG_OLD_DIR} ${CFG_NEW_DIR} ) then vewarn "Skipping ${CFG_NEW_FILE} generation (file is newer than dependencies)" else generated_ok=0 tmpfile="${CFG_NEW_FILE}.$$" # # First we try to use regular generate-modprobe.conf # if ${GENERATE_OLD} ; then # Make sure that generate-modprobe.conf can handle --assume-kernel # if we were called with it. if [[ -n ${ASSUME_KV} ]] && \ ! grep -qe --assume-kernel /sbin/generate-modprobe.conf ; then eerror "Error: update-modules called with --assume-kernel flag, but" eerror "generate-modprobe.conf doesn't understand it. You need to" eerror "install >=module-init-tools-3.0-r2" exit 3 fi ebegin "Updating ${CFG_NEW_FILE}" echo "${FULLHEADER//@MODDIR@/${CFG_NEW_DIR}}" > "${tmpfile}" if generate-modprobe.conf ${ASSUME_KV:+--assume-kernel=${KV}} \ >> "${tmpfile}" 2> "${tmpfile}.err" then backup "${CFG_NEW_FILE}" "${tmpfile}" eend 0 generated_ok=1 else [[ ${VERBOSE} -gt 0 ]] && cat "${tmpfile}.err" eend 1 "Warning: could not generate ${CFG_NEW_FILE}!" fi fi # # If the helper script failed, we fall back to doing it by hand # if [[ ${generated_ok} -eq 0 ]] ; then ebegin "Updating ${CFG_NEW_FILE} by hand" generate_config "${CFG_NEW_FILE}" "${CFG_OLD_DIR}" "${CFG_NEW_DIR}" 0 echo "${FULLHEADER//@MODDIR@/${CFG_NEW_DIR}}" > "${tmpfile}" # Just use generate-modprobe.conf to filter compatible syntax if TESTING_MODPROBE_CONF=${CFG_NEW_FILE} \ 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}" "${CFG_NEW_FILE}" eend $? else [[ ${VERBOSE} -gt 0 ]] && cat "${tmpfile}.err" eend 1 "Warning: could not generate ${CFG_NEW_FILE}!" 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 ${CFG_NEW_FILE} ]] ; then for cfg in "${CFG_NEW_DIR}"/* ; do [[ -d ${cfg} ]] && continue [[ ! -r ${cfg} ]] && continue # Skip backup and RCS files; fixes bug 20597 (07 May 2004 agriffis) [[ ${cfg} == *~ || ${cfg} == *.bak || ${cfg} == *,v ]] && continue echo >> "${CFG_NEW_FILE}" echo "### update-modules: start processing ${cfg}" >> "${CFG_NEW_FILE}" cat "${cfg}" >> "${CFG_NEW_FILE}" echo "### update-modules: end processing ${cfg}" >> "${CFG_NEW_FILE}" done fi rm -f "${tmpfile}" "${tmpfile}.err" # # Take care of generating /etc/modprobe.devfs if need be. # if ${GENERATE_DEVFS} && [[ -f ${CFG_OLD_DEVFS} ]] && \ ( [[ ! -e ${CFG_NEW_DEVFS} ]] || [[ ${CFG_OLD_DEVFS} -nt ${CFG_NEW_DEVFS} ]] || ${FORCE} ) then ebegin "Updating ${CFG_NEW_DEVFS}" tmpfile="${CFG_NEW_DEVFS}.$$" tmpfile_old="${CFG_OLD_DEVFS}.$$" echo "${FULLHEADER/@MODDIR@/${CFG_NEW_DIR}}" > "${tmpfile_old}" cp -f "${tmpfile_old}" "${tmpfile}" gawk '$0 !~ /^[[:space:]]*include/ { print $0 }' \ "${CFG_OLD_DEVFS}" >> "${tmpfile_old}" if TESTING_MODPROBE_CONF=${tmpfile_old} \ generate-modprobe.conf ${ASSUME_KV:+--assume-kernel=${KV}} \ >> "${tmpfile}" 2> "${tmpfile}.err" then echo >> "${tmpfile}" echo "include /etc/modprobe.conf" >> "${tmpfile}" backup "${CFG_NEW_DEVFS}" "${tmpfile}" eend 0 else [[ ${VERBOSE} -gt 0 ]] && cat "${tmpfile}.err" eend 1 "Warning: could not generate ${CFG_NEW_DEVFS}!" rm -f "${tmpfile}" fi backup "${CFG_OLD_DEVFS}" "${tmpfile_old}" rm -f "${tmpfile_old}" "${tmpfile}" "${tmpfile}.err" fi fi # # Call depmod to keep insmod from complaining that modules.conf is more # recent then the modules.dep file. # grab_depfile() { # the modules.conf file has optional syntax: # depfile=/path/to/modules.dep local ret="" if [[ -e ${CFG_OLD_FILE} ]] ; then ret=$(sed -n -e '/^[[:space:]]*depfile=/s:.*=::p' ${CFG_OLD_FILE}) fi [[ -z ${ret} ]] && ret="/lib/modules/${KV}/modules.dep" eval echo "${ret}" } depfile=$(grab_depfile) if [[ -d ${depfile%/*} ]] ; then if [[ ${CFG_NEW_FILE} -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} -${KV} "" ; do scfg=$(echo ${cfg}${suffix}) scfg=${scfg%% *} [[ -f ${scfg} ]] && cfg=${scfg} && break 2 done cfg="" done [[ -n ${cfg} ]] && cfg="-F ${cfg}" depmod -a ${cfg} ${KV} eend $? [[ ${VERBOSE} -gt 0 ]] && einfo "Ran: depmod -a ${cfg} ${KV}" fi else vewarn "The dir '${depfile}' does not exist, skipping call to depmod" fi exit 0