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 && -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 () { if [[ ! -e "$TMPDIR/root/$1" ]]; then msg " adding dir ${1}" command install -dm755 "$TMPDIR/root/$1" fi } 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 [[ ! -e "$TMPDIR/root/$dest" ]]; then msg " adding link ${fil} -> ${dest}" ln -s "$dest" "$TMPDIR/root/$fil" fi fi #fail quietly } add_file() { local file dest file=$1 dest=${2:-${file##$BASEDIR}} if [[ -f "$file" ]]; then if [[ -L "$file" ]]; then add_symlink "$file" "$(readlink -f "$file")" add_file "$(readlink -f "$file")" return fi if [[ ! -e "$TMPDIR/root/$dest" ]]; then msg " adding file $dest" command install -Dm$(stat -c '%a' "$file") "$file" "$TMPDIR/root/$dest" fi else err "file '$file' 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: