summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Reisner <d@falconindy.com>2011-06-18 02:01:35 +0200
committerThomas Bächler <thomas@archlinux.org>2011-06-25 12:25:45 +0200
commit840893e2b37470749d11e249becdba40b91adc92 (patch)
tree471e03e8ef170ad7cee9803c108673348a12f629
parent99c2b87cdbc3f449b68ed6d0bf2fec624d539972 (diff)
downloadmkinitcpio-840893e2b37470749d11e249becdba40b91adc92.tar.gz
mkinitcpio-840893e2b37470749d11e249becdba40b91adc92.tar.xz
properly support $BASEDIR
This add proper support for a $BASEDIR, wherein as much as possible is taken from the user specified root, instead of mixing and matching binaries and modules. This avoids conflicts, particularly with binaries like udev or module-init-tools which may have newer functionality that the root in the $BASEDIR requires. This is somewhat of a large patch, which involves a few key changes: 1) Add a new class of "private" functions: _add_*, which act as a "back end" for the equivalent non-underscore-prefixed functions. 2) Refactor the add_* family of functions to use these new back end functions. This generally simplifies the logic as we have a clear division of labor. 3) Instead of using ldd, which is a glorified wrapper around the RTLD, create a wrapper around the RTLD and invoke it ourselves. This is basically just a small performance improvement -- the bulk of the parsing done by this function's output is done in pure bash. Signed-off-by: Dave Reisner <d@falconindy.com>
-rw-r--r--functions139
-rwxr-xr-xmkinitcpio20
2 files changed, 108 insertions, 51 deletions
diff --git a/functions b/functions
index 580e636..ab0f850 100644
--- a/functions
+++ b/functions
@@ -124,10 +124,11 @@ add_dir() {
# Add a directory to the initcpio image.
# $1: absolute path of directory on image
- if [[ ! -e "$BUILDROOT/$1" ]]; then
- (( QUIET )) || plain "adding dir: %s" "$1"
- command install -dm755 "$BUILDROOT/$1"
- fi
+ (( ! $# )) && return 1
+
+ local path=$1 mode=${2:-755}
+
+ _add_dir "$path" "$mode"
}
add_symlink() {
@@ -135,13 +136,10 @@ add_symlink() {
# $1: pathname of symlink on image
# $2: absolute path to target of symlink
- local file=$1 dest=$2
+ (( $# == 2 )) || return 1
- add_dir $(get_dirname "$file")
- if [[ ! -e "$TMPDIR/root/$dest" ]]; then
- (( QUIET )) || plain "adding symlink: $file -> $dest"
- ln -s "$dest" "$BUILDROOT/$file"
- fi
+ _add_dir "$(get_dirname "$1")"
+ _add_symlink "$2" "$1"
}
add_file() {
@@ -150,26 +148,22 @@ add_file() {
# $1: path to file
# $2: destination on initcpio (optional, defaults to same as source)
- local file dest
+ (( $# )) || return 1
- file=$1
- dest=${2:-${file##$BASEDIR}}
+ # determine source and destination
+ local src= dest=${2:-$1} mode=
- if [[ -f "$file" ]]; then
- if [[ -L "$file" ]]; then
- add_symlink "$file" "$(readlink -f "$file")"
- add_file "$(readlink -f "$file")"
- return
- fi
+ src=$BASEDIR$1
- if [[ ! -e "$BUILDROOT/$dest" ]]; then
- (( QUIET )) || plain "adding file: %s" "$dest"
- command install -Dm$(stat -c '%a' "$file") "$file" "$BUILDROOT/$dest"
- fi
- else
- error "file '$file' does not exist"
+ [[ -f "$src" ]] || { error "$src: No such file"; return 1; }
+
+ mode=$(stat -c %a "$src")
+ if [[ -z "$mode" ]]; then
+ error "failed to stat file: \`$src'"
return 1
fi
+
+ _add_file "${dest#$BASEDIR}" "$src" "$mode"
}
add_module() {
@@ -213,40 +207,85 @@ add_module() {
esac
}
+_ldd() {
+ LD_TRACE_LOADED_OBJECTS=1 "$LD_SO" "$@"
+}
+
+_add_file() {
+ # add a file to $BUILDROOT
+ # $1: pathname on initcpio
+ # $2: source on disk
+ # $3: mode
+
+ (( $# == 3 )) || return $EINVAL
+ [[ -e "$BUILDROOT$1" ]] && return $EEXIST
+
+ (( QUIET )) || plain "adding file: %s" "$1"
+ install -Dm$3 "$2" "$BUILDROOT$1"
+}
+
+_add_dir() {
+ # add a directory (with parents) to $BUILDROOT
+ # $1: pathname on initcpio
+ # $2: mode
+
+ (( $# == 2 )) || [[ "$1" == /?* ]] || return 1 # bad args
+ [[ -e "$BUILDROOT$1" ]] && return 0 # file exists
+
+ (( QUIET )) || plain "adding dir: %s" "$1"
+ command install -dm$2 "$BUILDROOT$1"
+}
+
+_add_symlink() {
+ # add a symlink to $buildroot
+ # $1: name on initcpio
+ # $2: target of $1
+
+ (( $# == 2 )) || return $EINVAL
+ [[ -L "$BUILDROOT$1" ]] && return $EEXIST
+
+ (( QUIET )) || plain "adding symlink: %s -> %s" "$2" "$1"
+ ln -s "$2" "$BUILDROOT$1"
+}
+
add_binary() {
# add a binary file to the initcpio image. library dependencies will
# be discovered and added.
# $1: path to binary
# $2: destination on initcpio (optional, defaults to same as source)
- local bin dest lib
+ local -a sodeps
+ local regex binary dest mode sodep resolved dirname
- bin=$(type -P "$1")
- dest=$2
+ binary=$BASEDIR$1
- if [[ ! -f "$bin" ]]; then
- error "'$1' is not a file"
- return 1
- fi
+ [[ -f "$binary" ]] || { error "$binary not found"; return 1; }
- case "$(file -b "$bin")" in
- *script*)
- plain "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]\+)//')
- ;;
- *)
- error "unknown type '$type' for binary '$bin'"
- return 1
- ;;
- esac
+ dest=${2:-$binary}
+ mode=$(stat -c %a "$binary")
+
+ # always add the binary itself
+ _add_file "${dest#$BASEDIR}" "${binary#$BASEDIR}" "$mode"
+
+ $LD_SO --verify "$binary" &>/dev/null || return # not a binary!
+
+ # resolve sodeps
+ regex='^[[:space:]]*[^/].+ => (.*) \(.*\)'
+ while read line; do
+ [[ "$line" =~ $regex ]] && sodep=${BASH_REMATCH[1]} || continue
+
+ if [[ -f "$sodep" ]]; then # -f follows symlinks, don't believe it!
+ if [[ ! -L $sodep ]]; then
+ _add_file "$sodep" "$BASEDIR$sodep" "$(stat -c %a "$sodep")"
+ else
+ resolved=$(readlink -e "$basedir$sodep")
+ dirname=${resolved%/*}
+ _add_dir "${dirname#$basedir}" 755
+ _add_symlink "$sodep" "${resolved#$BASEDIR}"
+ _add_file "${resolved#$BASEDIR}" "$resolved" 755
+ fi
+ fi
+ done < <(_ldd "$binary")
}
parse_hook() {
diff --git a/mkinitcpio b/mkinitcpio
index 85e81b2..4082ba5 100755
--- a/mkinitcpio
+++ b/mkinitcpio
@@ -14,6 +14,7 @@ shopt -s extglob
# Settings
KERNELVERSION=$(uname -r)
+CARCH=$(uname -m)
FUNCTIONS=functions
CONFIG=mkinitcpio.conf
HOOKDIR=hooks
@@ -21,7 +22,7 @@ INSTDIR=install
PRESETDIR=mkinitcpio.d
COMPRESSION=gzip
-declare TMPDIR BASEDIR MODULE_FILE GENIMG PRESET COMPRESSION_OPTIONS BUILDROOT
+declare TMPDIR BASEDIR MODULE_FILE GENIMG PRESET COMPRESSION_OPTIONS BUILDROOT LD_SO
declare NC= BOLD= BLUE= GREEN= RED= YELLOW=
declare -i QUIET=1 SHOW_AUTOMODS=0 SAVELIST=0 COLOR=1
declare -a SKIPHOOKS ADDED_MODULES
@@ -285,6 +286,23 @@ trap '[[ $FUNCNAME = parse_hook ]] && (( ++builderrors ))' ERR
#parse 'global' hook, as defined in ${CONFIG}
parse_hook
+# resolve the linker and add it
+case $CARCH in
+ i686) LD_SO=("$BASEDIR"/lib/ld-linux.so.?*) ;;
+ x86_64) LD_SO=("$BASEDIR"/lib/ld-linux-${CARCH//_/-}.so.?*) ;;
+ *) die "unknown architecture: $CARCH" ;;
+esac
+
+if (( ${#LD_SO[*]} != 1 )); then # uh oh...
+ die "failed to resolve the location of /lib/ld.so. Please report this bug."
+fi
+
+resolved=$(readlink -e "$LD_SO")
+_add_dir "${resolved%/*}" 755
+_add_symlink "${LD_SO#$BASEDIR}" "${resolved#$BASEDIR}"
+_add_file "${resolved#$BASEDIR}" "${resolved#$BASEDIR}" 755
+unset resolved
+
for hook in ${HOOKS}; do
in_array "$hook" "${SKIPHOOKS[@]}" && continue
unset MODULES BINARIES FILES SCRIPT