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 } auto_modules () { aliases="$(find /sys/devices/ -name modalias -exec cat {} +)" mods="" for a in $aliases; do m="$(modprobe --set-version ${KERNELVERSION} --resolve-alias "$a")" [ -n "$m" ] && mods="$mods $m" done echo "${mods}" | tr '-' '_' [ -z "${mods}" ] && return 1 return 0 } all_modules () { mods=$(find ${MODULEDIR} -name '*.ko' -or -name '*.ko.gz' 2>/dev/null | grep $@ | sort -u) echo "${mods}" [ -z "${mods}" ] && return 1 return 0 } checked_modules () { if [ -e "${MODULE_FILE}" ]; then for mod in $(all_modules $@); do modname=$(get_module_name "${mod}") if grep -q "^${modname}$" "${MODULE_FILE}"; then echo ${modname} fi done 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 } # add_device /dev/foo type major minor [permissions] add_device () { if [ $# -ge 4 ]; then local perms perms="${5:-644}" if ! grep -q "nod ${1}" "${FILELIST}"; then add_dir $(get_dirname "${1}") msg " adding node ${1}" echo "nod ${1} ${perms} 0 0 ${2} ${3} ${4}" >> "${FILELIST}" fi else err "invalid device node format: $@" return 1 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 [ $# -eq 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 } HAS_MODULES="n" declare -a ADDED_MODULES #modules are handled specially in order to enable autodetection add_module () { local m fil path fw mod deps m=$(get_module_name "${1}") #find pattern - replace _ with [-_] to match either fil="${m//_/[-_]}" #skip expensive stuff if this module has already been added if in_array $m ${ADDED_MODULES[@]}; then msg "module $m was already added" return fi found=0 for path in $(find "${MODULEDIR}" -type f -name "${fil}.ko" -or -name "${fil}.ko.gz"); do #get needed firmware files for fw in $(/sbin/modinfo -F firmware "${path}"); do [ -f "/lib/firmware/$fw" ] && add_file "/lib/firmware/$fw" done #get module depends deps="$(/sbin/modinfo -F depends "${path}")" for mod in ${deps//,/ }; do if [ -n "${mod}" ]; then add_module "${mod}" fi done HAS_MODULES="y" ADDED_MODULES[${#ADDED_MODULES[*]}]="$m" msg " adding module ${fil}" add_file "${path}" && found=1 done if [ ${found} -eq 1 ]; then #explicit module depends case "$m" in fat) add_module "nls_cp437" ;; ocfs2) add_module "configfs" ;; libcrc32c) add_module "crc32c"; add_module "crc32c_intel" ;; esac else err "module '$m' not found" fi } add_binary () { local bin dest type lib bin=$(which "${1}") if [ $? -ne 0 ]; then bin="${1}" fi dest="" if [ $# -eq 2 ]; then dest=${2} fi if [ ! -f "${bin}" ]; then err "'${bin}' is not a file" return 1 fi if [ $? -eq 0 ]; then type=$(file -b "${bin}") case "${type}" in *script*) msg " adding '${type}' script, ensure proper interp exists..." add_file "${bin}" ${dest} ;; *executable*|*shared\ object*|*symbolic\ link*) add_file "${bin}" ${dest} #note, this will also handle 'not a dynamic executable' spit out by # static binaries... the deps will produce nothing for lib in $(ldd ${bin} 2>/dev/null | sed "s|.*=>\(.*\)|\1|"); do if [ -n "${lib}" ]; then #remove TLS libraries notls=$(echo ${lib} | sed 's|/lib/tls.*/\(lib.*\)|/lib/\1|') [ -e "${notls}" ] && lib="${notls}" [ -f "${lib}" ] && add_file "${lib}" fi done ;; *) err "unknown type '${type}' for binary '${bin}'" return 1 ;; esac fi } 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: