#!/bin/sh -efu

. sh-functions
. shell-error

canonicalize_file() {
	local __canonicalize_file_name="$1" __canonicalize_file_result
	__canonicalize_file() {
		local fn="$1" r= t=
		while [ "$fn" != "$r" ]; do
			r="$fn"
			if [ -z "${fn##*//*}" ]; then
				fn="${fn%%//*}/${fn#*//}"
			elif [ -z "${fn##*/./*}" ]; then
				fn="${fn%%/./*}/${fn#*/./}"
			elif [ -z "${fn##*/../*}" ]; then
				t="${fn%%/../*}"
				t="${t%/*}"
				fn="$t/${fn#*/../}"
			elif [ -z "${fn##./*}" -o -n "${fn##/*}" ]; then
				fn="$PWD/${fn##./}"
			elif [ -z "${fn##*/}" ]; then
				fn="${fn%%/}"
			fi
		done
		__canonicalize_file_result="$fn"
	}
	__canonicalize_file "$2"
	eval "$__canonicalize_file_name=\$__canonicalize_file_result"
}

copy_regfile() {
	local fn="$1" dir

	canonicalize_file 'fn' "$fn"

	[ ! -e "$rootdir/$fn" ] ||
		return 1

	dir="$rootdir/${fn%/*}"
	[ -d "$dir" ] ||
		mkdir -p -- "$dir"

	cp -ad -- "$fn" "$dir/"
}

copy_symlink() {
	local fn="$1" l

	copy_regfile "$fn" ||
		return 0

	l="$(readlink -m -- "$fn")"
	copy "$l"
}

copy_elffile() {
	local fn="$1" libs

	copy_regfile "$fn" ||
		return 0

	# ignore all kernel modules.
	[ -n "${fn##$kernel_modules_dir/*.ko*}" ] ||
		return 0

	# avoid subshell incapsulation.
	libs="$(ldd -- "$fn" |sed -n 's/.*[[:space:]]\([^ ]\+\) (0x.*/\1/p')"

	for lib in $libs; do
		copy "$lib"
	done
}

copy() {
	local fn="$1" otype=

	[ ! -e "$fn" ] ||
		otype="$(file -b -- "$fn" 2>/dev/null)"

	case "$otype" in
		'')		# ignore nonexistent file
				error "$fn: No such file or directory"
				;;
		'broken symbolic link to '*)
				# ignore broken symlink
				error "$fn: Broken symlink"
				;;
		'symbolic link to '*)
				copy_symlink "$fn"
				;;
		'ELF '*|*' ELF '*)
				[ -n "${otype##* statically linked*}" ] &&
					copy_elffile "$fn" ||
					copy_regfile "$fn"
				;;
		*)
				copy_regfile "$fn"
				;;
	esac ||:
}

for fn; do
	[ -e "$fn" ] ||
		fatal "$fn: No such file or directory"

	copy "$fn"
done
