#!/bin/sh -efu

. shell-error
. shell-signal

prefix=
destdir=

print_version()
{
	cat <<-EOF
	put-file version 1.0
	Written by Alexey Gladkov.

	Copyright (C) 2012  Alexey Gladkov <gladkov.alexey@gmail.com>
	This is free software; see the source for copying conditions.  There is NO
	warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	EOF
	exit
}

show_help()
{
	cat <<-EOF

	Usage: put-file [<option>] <destdir> [directory|filename]...

	Options:
	   -r, --remove-prefix=STR   ignore prefix in path;
	   -v, --verbose             print a message for each action;
	   -V, --version             output version information and exit;
	   -h, --help                display this help and exit.

	Report bugs to authors.

	EOF
	exit
}

show_usage()
{
	[ -z "$*" ] || message "$*"
	echo "Try \`$PROG --help' for more information." >&2
	exit 1
}

workdir=
exit_handler()
{
	[ -z "$workdir" ] || rm -rf -- "$workdir"
}

TEMP=`getopt -n $PROG -o 'r:,h,v,V' -l 'remove-prefix:,help,verbose,version' -- "$@"` ||
	show_usage
eval set -- "$TEMP"

while :; do
	case "$1" in
		-r|--remove-prefix) shift
			prefix="$1"
			;;
		-h|--help)
			show_help
			;;
		-v|--verbose)
			verbose=-v
			;;
		-V|--version)
			print_version
			;;
		--) shift
			break
			;;
		*)
			fatal "Unknown option: $1"
			;;
	esac
	shift
done

[ "$#" -gt 0 ] ||
	show_usage "More arguments required"

destdir="$1"
shift

[ -d "$destdir" ] ||
	mkdir -p -- "$destdir"

set_cleanup_handler exit_handler
workdir="$(mktemp -dt "$PROG.XXXXXXXXX")"

printf '%s\n' "$@" > "$workdir"/fn

while :; do
	do_break=1

	while read fn; do
		[ -L "$fn" -o -e "$fn" ] ||
			continue

		if [ ! -L "$fn" -a -d "$fn" ]; then
			find "$fn" -mindepth 1 -maxdepth 1
			do_break=
			continue
		fi

		cd "${fn%/*}"
		fn="$PWD/${fn##*/}"
		cd - >/dev/null

		new="${fn#$prefix}"

		[ ! -L "$destdir/$new" -a ! -e "$destdir/$new" ] ||
			continue

		do_break=

		d="$destdir/${new%/*}"
		[ -d "$d" ] ||
			mkdir $verbose -p -- "$d" >&2

		cp $verbose -aud "$fn" "$destdir/$new" >&2

		[ ! -L "$fn" ] ||
			readlink -ev "$fn" 2>/dev/null ||:

	done < "$workdir"/fn > "$workdir"/fn.new

	[ -z "$do_break" ] ||
		break

	elfcheck -f - < "$workdir"/fn > "$workdir"/fn.elf

	[ ! -s "$workdir"/fn.elf ] ||
		xargs -r ldd < "$workdir"/fn.elf |
			sed -r -n 's,^\t(.* => )?([^ ]+) \(0x[0-9a-f]+\)$,\2,p' >> "$workdir"/fn.new

	mv -f "$workdir"/fn.new "$workdir"/fn
done
