blob: 206521ce8a48b5f861181c22bed98d09e0ee89c0 [file] [log] [blame]
#!/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 <old config file to backup> <new config file to replace with>
# 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 <config dir>
# 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 <output config file> <config dir> <reference config dir> <silent>
# 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