#!/bin/sh
#/
#/ \file
#/
#/ \brief   manage software set image files
#/
#/ \author  Arthur Rinkel
#/
#/ \date    April 18, 2014
#/

readonly BASENAME=`basename $0`
readonly VERSION="0.1"

readonly MKDIRHIER="mkdir -p"

readonly DEF_DIR="."

#-------------------------------------------------------------------------------

#/
#/ Output script usage and exit.
#/
#/ \returns
#/ Always exit code 1.
#/
usage()
{
	cat <<_EOF

Usage: $BASENAME <OPTIONS> <IMAGE>

Tool for managing image files of Software Sets. An image file can be created
given the root directory of a Software Set, or an image can be installed in
in a certain directory. When creating an image file, the Software Set directory
is stripped from the files in the image.

OPTIONS

  -c        create image of Software Set in directory specified by "-d" option
  -i        install Software Set in image in directory specified by "-d" option
  -t        check image integrity
  -d DIR    use directory DIR (default: $DEF_DIR)
  -f        force operation, don't ask questions
  -v        be verbose
  -h        show this help and exit
  -V        show version and exit
_EOF

	exit 1
}

#/
#/ Output script version and exit.
#/
#/ \returns
#/ Always exit code 1.
#/
version()
{
	cat <<_EOF
$BASENAME $VERSION
_EOF

	exit 1
}

#/
#/ Create image from given directory.
#/
#/ \param[in] $1  Name of image to create.
#/ \param[in] $2  Directory to image.
#/
create_image()
{
	local img="$1"
	local srcdir="$2"
	local file=""
	local v=""
	local -i ret=1

	[ -n "$srcdir" ] || return 1

	file=`readlink -f "$img" 2>/dev/null`

	if test $VERBOSE -eq 1; then
		v=-v
	fi

	# abort if archive should not be overwritten:
	if test $FORCE -eq 0 -a -f "$file"; then
		echo "$BASENAME: $file: image already exists" 2>&1
		return 1
	fi

	if test -d "$srcdir"; then
		cd "$srcdir"
		find . -depth -print 2>/dev/null | cpio -oa $v -Hcrc --quiet >$file
		ret=$?
	else
		echo "$BASENAME: $srcdir: directory does not exist" 2>&1
	fi

	return $ret
}

#/
#/ Install image in given directory.
#/
#/ \param[in] $1  Name of image to install.
#/ \param[in] $2  Directory where to install image.
#/
install_image()
{
	local img="$1"
	local dstdir="$2"
	local file=""
	local u=""
	local v=""

	file=`readlink -e "$img" 2>/dev/null`
	if test $? -ne 0; then
		echo "$BASENAME: $img: file not found" 2>&1
		exit 1
	fi

	if test $FORCE -eq 1; then
		u=-u
	fi
	if test $VERBOSE -eq 1; then
		v=-v
	fi

	if test ! -d "$dstdir"; then
		$MKDIRHIER "$dstdir"
	fi
	cd "$dstdir" && \
	  cpio -imd $u $v --quiet --no-absolute-filenames --no-preserve-owner <$file
}

#/
#/ Check integrity of image file.
#/
#/ \param[in] $1  Name of image to check.
#/
test_image()
{
	local img="$1"
	local file=""
	local v=""
	local -i ret=1

	if test $VERBOSE -eq 1; then
		v=-v
	fi

	file=`readlink -e "$img" 2>/dev/null`
	if test $? -eq 0; then
		cpio -i $v --only-verify-crc <$file
		ret=$?
	else
		echo "$BASENAME: $img: file not found" 2>&1
	fi

	return $ret
}

#-------------------------------------------------------------------------------

MODE=
DIR="$DEF_DIR"
declare -i FORCE=0
declare -i VERBOSE=0

while getopts :citd:fvhV OPT
do
	case "$OPT" in
	c) MODE=create
	   ;;
	i) MODE=install
	   ;;
	t) MODE=test
	   ;;
	d) DIR="$OPTARG"
	   ;;
	f) FORCE=1
	   ;;
	v) VERBOSE=1
	   ;;
	h) usage
	   ;;
	V) version
	   ;;
	?) echo "$OPTARG -- unknown option" 2>&1
	   usage
	   ;;
	:) echo "$OPTARG -- missing argument" 2>&1
	   usage
	   ;;
	esac
done
# get image name:
shift `expr $OPTIND '-' 1 2>/dev/null`
IMAGE="$1"

if test -n "$IMAGE"; then
	case "$MODE" in
	create)  create_image "$IMAGE" "$DIR" ;;
	install) install_image "$IMAGE" "$DIR" ;;
	test)    test_image "$IMAGE" ;;
	*) echo "$BASENAME: missing or unsupported mode \`$MODE'" 2>&1
	   exit 1
	   ;;
	esac
else
	echo "$BASENAME: missing image file"
	usage
fi
