msg () { [ "${QUIET}" = "n" ] && echo $@; } err () { echo "ERROR: $@" >&2; } die () { echo "FATAL: $@" >&2; cleanup; exit 1; } get_dirname () { # strip any trailing slash first... local dir="${1%/}" # then get the directory portion echo "${dir%/*}" } get_basename () { echo "${1##*/}" } get_module_name () { #cleanup - remove .ko, replace - with _ local modname="${1%.gz}" modname=$(get_basename "${modname%.ko}") modname="${modname//-/_}" echo "$modname" } ## # usage : in_array( $needle, $haystack ) # return : 0 - found # 1 - not found ## in_array() { local needle=$1; shift [[ -z $1 ]] && return 1 # Not Found local item for item in "$@"; do [[ $item = $needle ]] && return 0 # Found done return 1 # Not Found } kmodinfo() { modinfo -b "$BASEDIR" -k "$KERNELVERSION" "$@" 2>/dev/null } auto_modules () { IFS=$'\n' read -rd '' -a mods < \ <(find /sys/devices -name modalias -exec sort -zu {} + | xargs -0 modprobe -aRS "$KERNELVERSION" | sort -u) printf "%s\n" "${mods[@]//-/_}" (( ${#mods[*]} )) } all_modules () { local -i count=0 while read -r -d '' mod; do (( ++count )) mod=${mod##*/} mod="${mod%.ko*}" printf '%s\n' "${mod//-/_}" done < <(find "$MODULEDIR" -name '*.ko*' -print0 2>/dev/null | grep -Zz "$@") (( count )) } checked_modules () { if [[ -s "$MODULE_FILE" ]]; then grep -xFf "$MODULE_FILE" <(all_modules "$@") return 1 else all_modules "$@" fi } add_full_dir () { if [ -n "${1}" -a -d "${1}" ]; then for f in ${1}/*; do if [ -d "${f}" ]; then add_full_dir "${f}" else add_file "${f}" fi done fi } add_dir () { #skip root directory and "." for relative directories... i.e. /foo/bar/./blah if [ -n "${1}" -a "${1}" != "/" -a "${1}" != "." ]; then if ! grep -q "dir ${1} " "${FILELIST}"; then add_dir $(get_dirname "${1}") msg " adding dir ${1}" echo "dir ${1} 755 0 0" >> "${FILELIST}" fi fi } # what the hell does this do? add_symlink () { local fil dest dir if [ -h ${1} ]; then fil="${1##$BASEDIR}" dest="${2##$BASEDIR}" add_dir $(get_dirname "${dest}") add_dir $(get_dirname "${fil}") if ! grep -q "slink ${fil} " "${FILELIST}"; then msg " adding link ${fil} -> ${dest}" echo "slink ${fil} ${dest} $(stat -c '%a' ${1}) 0 0" >> "${FILELIST}" fi fi #fail quietly } add_symlink2 () { add_dir $(get_dirname ${1}) add_dir $(get_dirname ${2}) if ! grep -q "slink ${1} " "${FILELIST}"; then msg " adding link ${1} -> ${2}" echo "slink ${1} ${2} 777 0 0" >> "${FILELIST}" fi } add_file () { local fil lnk dir dest if [ -f "${1}" ]; then fil="${1}" lnk=$(readlink -f "${fil}") if [ -n "${lnk}" ]; then add_symlink "${fil}" "${lnk}" fil="${lnk}" fi if [[ $2 ]]; then dest="${2}" else dest="${fil##$BASEDIR}" if [ "${dest}" = "${dest#/}" ]; then dest="/${dest}" fi fi add_dir $(get_dirname "${dest}") if ! grep -q "file ${dest} " "${FILELIST}"; then msg " adding file ${dest}" echo "file ${dest} ${fil} $(stat -c '%a' ${fil}) 0 0" >> "${FILELIST}" fi else err "file '${1}' does not exist" return 1 fi } declare -a ADDED_MODULES #modules are handled specially in order to enable autodetection add_module () { local module path fw dep deps module=${1%.ko*} #skip expensive stuff if this module has already been added if in_array $module ${ADDED_MODULES[@]}; then msg "module $module was already added" return fi path=$(kmodinfo -0F filename "$module") if [[ $path ]]; then # get module firmware while read -r -d '' fw; do if [[ -e "$BASEDIR/lib/firmware/$fw" ]]; then add_file "$BASEDIR/lib/firmware/$fw" fi done < <(kmodinfo -0F firmware "$module") # get module depends IFS=',' read -r -d '' -a deps < <(kmodinfo -0F depends "$module") for dep in "${deps[@]}"; do add_module "$dep" done ADDED_MODULES+=("$module") msg " adding module $module" add_file "$path" || return else err "module '$module' not found" return fi # explicit module depends case "$module" in fat) add_module "nls_cp437" ;; ocfs2) add_module "configfs" ;; libcrc32c) add_module "crc32c"; add_module "crc32c_intel" ;; esac } add_binary () { local bin dest lib bin=$(type -P "$1") dest=$2 if [[ ! -f "$bin" ]]; then err "'$1' is not a file" return 1 fi case "$(file -b "$bin")" in *script*) msg " adding '${type}' script, ensure proper interp exists..." add_file "$bin" ${dest+"$dest"} ;; *executable*|*shared\ object*|*symbolic\ link*) add_file "$bin" ${dest+"$dest"} # note, this will also handle 'not a dynamic executable' spit out # by static binaries... the deps will produce nothing while read -r lib; do [[ -f "$lib" ]] && add_file "$lib" done < <(ldd "$bin" 2>/dev/null | sed '1d;s|.*=>\(.*\)|\1|;s/(0x[0-9a-f]\+)//') ;; *) err "unknown type '$type' for binary '$bin'" return 1 ;; esac } parse_hook () { local mod bin fil for mod in ${MODULES}; do if [ -n "${mod}" ]; then add_module "${mod}" fi done for bin in ${BINARIES}; do if [ -n "${bin}" ]; then add_binary "${bin}" fi done for fil in ${FILES}; do if [ -n "${fil}" ]; then add_file "${fil}" fi done if [ -n "${SCRIPT}" ]; then add_file "${HOOKDIR}/${SCRIPT}" "/hooks/${SCRIPT}" fi } # vim: set ft=sh ts=4 sw=4 et: