#!/bin/bash
#
# functions used by mkinitrd and other tools.
#
# Copyright 2005-2008 Red Hat, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
# Authors:
# Peter Jones
# Jeremy Katz
# Jakub Jelinek
IF_RTLD=""
IF_dynamic=""
get_dso_deps() {
local bin="$1" ; shift
local FILES=() LDSO NAME IO FILE ADDR I1 n f TLIBDIR
LDSO=$(LANG=C eu-readelf -l $bin 2>/dev/null | \
awk '/interpreter/ {print $4}' |sed -e 's/]$//')
[[ $LDSO && $LDSO != $bin ]] || LDSO="$IF_RTLD"
[[ $LDSO && $LDSO != $bin ]] || return 1
[[ $IF_RTLD ]] || IF_RTLD="$LDSO"
# I love bash!
while read NAME I0 FILE ADDR I1 ; do
[[ $FILE = $bin ]] && continue
[[ $FILE = not || $NAME = not ]] && {
echo "Missing a shared library required by $bin." >&2
echo "dracut cannot create an initrd." >&2
return 1
}
# see if we are loading an optimized version of a shared lib.
[[ $FILE =~ '(/lib[^/]*).*' ]] && {
TLIBDIR=${BASH_REMATCH[1]}
BASE="${FILE##*/}"
# prefer nosegneg libs, then unoptimized ones.
for f in "$TLIBDIR/i686/nosegneg" "$TLIBDIR"; do
[[ -f $f/$BASE ]] || continue
FILE="$f/$BASE"
break
done
IF_dynamic="yes"
}
FILES+=("$FILE")
done < <(LD_TRACE_PRELINKING=1 LD_WARN= LD_TRACE_LOADED_OBJECTS=1 \
$LDSO $bin 2>/dev/null)
echo "${FILES[@]}"
}
inst() {
if (($# != 2 && $# != 3)); then
echo "usage: inst []"
return 1
fi
local file="$1" ; shift
local root="${1%%/}" ; shift
local dest="${1##/}"
[[ $dest ]] || dest="${file##/}"
mkdir -p "$root/${dest%/*}"
local RET=0
local target=""
[[ -L $file ]] && target=$(readlink "$file")
if [[ $target && $dest != $target ]]; then
if [[ -e $root/$dest ]]; then
RET=0
else
ln -sf "$target" "$root/$dest"
#inst "$target" "$root"
local BASE=${target##*/}
local LIBDIR=$(echo "$file" | sed -e 's,\(\(.*\)/\)[^/]\+$,\1,')
if [[ $LIBDIR = $BASE ]]; then
local LIBDIR=$(echo "/$dest" | sed -e 's,\(\(.*\)/\)[^/]\+$,\1,')
fi
local TLIBDIR=$(echo "$target" | sed -e 's,\(^/lib[^/]*\)/.*$,\1/,' \
-e 's,\(\(.*\)/\)[^/]\+$,\1,')
if [[ $TLIBDIR = $BASE ]]; then
local TLIBDIR=$(echo "/$dest" | sed \
-e 's,\(^/lib[^/]*\)/.*$,\1/,' \
-e 's,\(\(.*\)/\)[^/]\+$,\1,')
fi
inst "$LIBDIR/$BASE" "$root" "$TLIBDIR/$BASE"
RET=$?
return $RET
fi
fi
local SHEBANG=$(dd if="$file" bs=2 count=1 2>/dev/null)
if [[ $SHEBANG = '#!' ]]; then
# We're intentionally not playing the "what did this moron run
# in his shell script" game. There's nothing but pain in that.
local interp=$(head -1 "$file" | sed 's/^#! *//')
inst "$interp" "$root"
RET=$?
return $RET
fi
if [[ -e $root/$dest ]]; then
RET=0
else
if [[ $target && -L $target ]]; then
inst "$target" "$root"
RET=$?
else
cp -aL "$file" "$root/$dest"
local DEPS=$(get_dso_deps "$file")
if [[ $DEPS ]]; then
for x in $DEPS; do
local TLIBDIR=$(echo "$x" | sed 's,\(/lib[^/]*\)/.*$,\1,')
local BASE=$(basename "$x")
inst "$x" "$root" "$TLIBDIR/$BASE"
done
RET=$?
fi
fi
fi
return $RET
}
modcat="/lib/modules/$kernel/modules"
instmods() {
local mod mpargs modpath modname cmd
while (($# > 0)); do
mod=${1%.ko}
case $mod in
=ata) instmods $mpargs $(cat "${modcat}.block" |egrep 'ata|ahci');;
=*) instmods $mpargs $(cat "${modcat}.${mod#=}");;
--*) mpargs+=" $mod";;
*) modprobe $mpargs --set-version $kernel --show-depends $mod \
2>/dev/null |while read cmd modpath; do
[[ $cmd = insmod ]] || continue
modname=${modpath##*/}
modname=${modname%.ko}
[[ ${mod/-/_} != ${modname/-/_} ]] && {
instmods $mpargs $modname
continue
}
inst "$modpath" "$initdir" "/lib/modules/$kernel/$modname.ko"
done
;;
esac
shift
done
for fw in $(/sbin/modinfo -F firmware $mod 2>/dev/null); do
if [ -f /lib/firmware/$fw ]; then
inst_simple "/lib/firmware/$fw"
fi
done
}
findkeymap () {
local MAP=$1
[[ ! -f $MAP ]] && \
MAP=$(find /lib/kbd/keymaps -type f -name $MAP -o -name $MAP.\* | head -n1)
[[ " $KEYMAPS " = *" $MAP "* ]] && return
KEYMAPS="$KEYMAPS $MAP"
case $MAP in
*.gz) cmd=zgrep;;
*.bz2) cmd=bzgrep;;
*) cmd=grep ;;
esac
for INCL in $($cmd "^include " $MAP | cut -d' ' -f2 | tr -d '"'); do
for FN in $(find /lib/kbd/keymaps -type f -name $INCL\*); do
findkeymap $FN
done
done
}
# vim:ts=8:sw=4:sts=4:et