#! /bin/sh

#
# archives-find                                                 (jh,08.11.2005)
#

#
#   archives-find: find files by filename or by md5sum in a file archives
#   Copyright (C) 2004, 2005  Jochen Hepp <jochen.hepp@gmx.de>
#
#   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, write to the Free Software
#   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#

script="${0##*/}"
date='08.11.2005'
version='0.0.7'

rcfile="$HOME/.${script}rc"
rc="~/.${script}rc"



# --------- usage ---------

print_usage () {
	cat <<-EOF
Usage: $script [-n|-f|-g] NAME ...

       NAME              filename or part of filename to find in archives
       -n  --name        search file by name
       -f  --file        search file by md5sum of an existing file
       -g  --generate    generate new md5sum list of directory NAME
       -V  --version     display version number
       -h  --help        display this help and exit
EOF
}



# --------- version ---------

print_version () {
	cat <<-EOF
		$script $version

		Copyright (C) 2004, 2005 Jochen Hepp
		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.

		Written by Jochen Hepp <jochen.hepp@gmx.de>.
EOF
}



# --------- search ---------

search () { # pattern   global: rc, resultfile
	local pattern="$1"
	local line

	# input format: path_to_list|path_to_dir

	# sed input format: RELATIVE_PATH_TO_LIST.md5sum:MD5SUM  PATH_TO_FILE

	while read line; do
		if [ -f "$line" ]; then
			{	grep -Hi "$pattern" "$line" && \
				if [ ! -s "$resultfile" ]; then
					echo "$line" >"$resultfile";
				fi;
			} | \
			sed "s!^${line%/*}/!!"
		elif [ -d "$line" ]; then
			{	grep -Hri "$pattern" "$line" && \
				if [ ! -s "$resultfile" ]; then
					echo "$line" >"$resultfile";
				fi;
			} | \
			sed "s!^${line%/}/!!"
		else
			echo "$script: $rc: $line: no such file or directory" >&2
		fi
	done | \
	sed 's/\.md5sum:/:/; s/:[0-9a-fA-F][0-9a-fA-F]*/:/; s%:.*/%: %'
}



# --------- switch_mode ---------

switch_mode () { # mode
	local mode="$1"
	local pattern
	local resultfile
	local result=0
	shift

	if [ "$mode" = 'generate' ]; then	
		while [ $# -gt 0 ]; do
			(	cd "$1" && \
				find . -type f -print0 | \
				xargs --null --no-run-if-empty md5sum )
			shift
		done

	else
		if [ ! -f "$rcfile" ]; then
			echo "$script: $rc: no such file" >&2
			exit 1
		fi
		if ! grep -c -v -e '^$' -e '^[ 	]*#' "$rcfile" >/dev/null; then
			echo "$script: $rc: no file or directory entries found" >&2
			exit 1
		fi

		resultfile="$(mktemp)"
		if [ ! -f "$resultfile" ]; then
			echo "$script: unable to create temporary file" >&2
			exit 1
		fi

		while [ $# -gt 0 ]; do
			file="$1"

			if [ "$mode" = 'byhash' -o \
			     \( "$mode" != 'byname' -a -r "$file" \) ]; then
				if [ ! -r "$file" ]; then
					echo "$script: $file: no such file" >&2
					rm -f "$resultfile"
					exit 1
				fi
				pattern="^`md5sum \"$file\" | sed -n '1 { s/ .*$//; p; q; }'`"
			else
				pattern="`echo \"$file\" | sed 's%^^%/%'`"
			fi

			grep -v -e '^$' -e '^#' "$rcfile" | \
			search "$pattern"

			shift
		done

		if [ ! -s "$resultfile" ]; then
			result=1
		fi
		rm -f "$resultfile"
	fi

	return "$result"
}



# --------- main ---------

# main {
	mode=
	count=0
	file=

	while [ $# -gt 0 ] && [ "${1#-}" != "$1" ]; do
		case "$1" in
			--version|-V)
				print_version
				exit 0
				;;
			--help|-h)
				print_usage
				exit 0
				;;
			--)
				shift
				break
				;;
			--name|-n)
				if [ "$mode" != 'byname' ]; then
					count="$(($count+1))"
				fi
				mode=byname
				;;
			--file|-f)
				if [ "$mode" != 'byhash' ]; then
					count="$(($count+1))"
				fi
				mode=byhash
				;;
			--generate|-g)
				if [ "$mode" != 'generate' ]; then
					count="$(($count+1))"
				fi
				mode=generate
				;;
			*)
				echo "$script: unrecognized option \`$1'" >&2
				echo "$script: Try \`$script --help' for more information." >&2
				exit 1
				;;
		esac
		shift
	done

	if [ "$count" -gt 1 ]; then
		echo "$script: You may not specify more than one \`-nfg' option" >&2
		echo "Try \`$script --help' for more information." >&2
		exit 1
	fi

	if [ $# -le 0 ]; then
		print_usage >&2
		exit 1
	fi

	switch_mode "$mode" "$@"
# }


# --- end ---

