#!/bin/ksh

##############################################################################
#                                                                            #
# Xtall -- install/remove software from archive                              #
#                                                                            #
# http://www.kpda.ru                                                         #
# http://forum.kpda.ru/index.php/topic,408.0.html                            #
#                                                                            #
# Copyright (c) CBD BC, 2010                                                 #
#                                                                            #
##############################################################################

##############################################################################
#                                                                            #
# Error list:                                                                #
#                                                                            #
# 1 -- Unknown options                                                       #
# 2 -- Unsupported file type                                                 #
# 3 -- Unknown action                                                        #
# 4 -- Can't find archive to remove                                          #
# 5 -- Too many archives to remove                                           #
# 6 -- File name doesn't specified                                           #
#                                                                            #
##############################################################################

##############################################################################
#                                                                            #
# Required utilities:                                                        #
#                                                                            #
# ksh                                                                        #
#                                                                            #
# tar, zcat, bzcat, freeze                                                   #
#                                                                            #
# basename                                                                   #
# find -- find archive to remove                                             #
# mkdir -- creating database directory                                       #
# rm -- to delete files                                                      #
# rmdir -- to delete directories                                             #
# sed -- print usage                                                         #
# sort -- to get list files to delete                                        #
# test -- check expressions                                                  #
# wc -- calculate archives count to remove                                   #
#                                                                            #
##############################################################################

##############################################################################
#                                                                            #
# Program defaults. Change this for your needs.                              #
#                                                                            #
##############################################################################

# An xtall data base path
xtall_db="/var/cache/xtall"		# QNX6
#xtall_db="/usr/xtall"			# QNX4

##############################################################################
#                                                                            #
# Usage message.                                                             #
#                                                                            #
##############################################################################

#ifdef __USAGE
#%C -- install/remove software from archive
#
#%C [options] <archive>
#
#Options:
# -f        Force operation
# -h        Print help and exit
# -i        Install files from archive (default action)
# -r        Remove installed files
# -V        Print version and exit
#
#endif

##############################################################################
#                                                                            #
# Internal variables. Don't change.                                          #
#                                                                            #
##############################################################################

# Action: i -- install, r -- remove (uninstall)
action="i"

# Force operation
force=

# Archive file name
filename=

# Program version
version="1.00A"

# Program name
progname=
fullname=

##############################################################################
#                                                                            #
# Functions.                                                                 #
#                                                                            #
##############################################################################

#
# Command line parser
#
parse_args() {

	fullname="$0"
	progname=`basename ${fullname}`

	while getopts fhirV opt ; do
		case "${opt}" in
			f)	force=1 ;;
			h)	view_help ;;
			i)	action="i" ;;
			r)	action="r" ;;
			V)	view_version ;;
			?)	print "Usage:"
				exit 1 ;;
		esac
	done

	shift $(($OPTIND -1))
	filename="$1"

	if test -z ${filename} ; then
		print "File name doesn't specified"
		exit 6
	fi
}

#
# View script version
#

view_version() {

	print "Xtall (${progname}) installer/remover ${version}  (c) CBD BC, 2010"
	exit 0
}

#
# View script help
#

view_help() {

	while read l ; do

		if test "${l}" = "#endif" ; then
			exit 0
		fi

		if test ! -z ${usagestart} ; then
			print ${l} | sed -e "s/#// ; s/^%C/"${progname}"/"
		fi

		if test "${l}" = "#ifdef __USAGE" ; then
			usagestart="1"
		fi

	done < ${fullname}
}

#
# Is current path root directory?
#
check_root_dir() {

	if test ! -z $force ; then
		return
	fi

	if test `pwd` == "/" ; then
		return
	fi

	print -n "You're not in root directory. Proceed anyway? (y/N): "
	read ans
	if test "y${ans}" != "yy" ; then
		print Exiting...
		exit 0
	fi
}

#
# Detect file type
#
file_ext() {

	case "$1" in
		*.tar)		print "tar" ;;
		*.tar.gz)	print "tgz" ;;
		*.tar.bz2)	print "tbz2" ;;
		*.tar.F)	print "tfz" ;;
		*)		print "unk"
	esac
}

# File type specific functions

unk_file_type() {

	print "Unsupported file type"
	exit 2
}

unk_list() {

	unk_file_type
}

unk_get() {

	unk_file_type
}

tar_list() {

	tar tf "$1"
}

tar_get() {

	tar xf "$1"
}

tgz_list() {

	zcat "$1" | tar t
}

tgz_get() {

	zcat "$1" | tar x
}

tbz2_list() {

	bzcat "$1" | tar t
}

tbz2_get() {

	bzcat "$1" | tar x
}

tfz_list() {

	freeze -cd "$1" | tar t
}

tfz_get() {

	freeze -cd "$1" | tar x
}

# Action functions

#
# Install from archive
#
xtall_install() {

	check_root_dir

	mkdir -p ${xtall_db}
	`file_ext "${filename}"`_list "${filename}" > ${xtall_db}/`basename "${filename}"`.txt
	`file_ext "${filename}"`_get "${filename}"
}

#
# Remove from cache
#
xtall_remove() {

	if test -e ${filename} ; then
		xtall_remove_from_archive
	fi

	filename=`basename "${filename}"`
	filename=`find ${xtall_db} -name "${filename}"'*' -print`
	filenum=`echo ${filename} | wc -w`

	if test ${filenum} -lt 1 ; then
		print "Can't find archive to remove"
		exit 4
	fi

	if test ${filenum} -gt 1 ; then
		print "Too many archives to remove:"
		for f in ${filename} ; do
			print "  "`basename ${f}`
		done
		exit 5
	fi

	print "Removing files from ${filename}"

	for f in `sort -r ${filename}` ; do
		if test -f ${f} -o -L ${f} ; then
			rm -f ${f}
		fi
		if test -d ${f} ; then
			rmdir ${f} > /dev/null 2>&1
			if test ! $? ; then
				print "Directory ${f} not empty, skipping..."
			fi
		fi
	done

	rm -rf ${filename}
}

#
# Remove from archive
#
xtall_remove_from_archive() {

	print "Removing from archive not implemented yet, sorry..."
#	exit 0
}

#
# Main function
#
main() {

	parse_args "$@"

	case ${action} in
		i) xtall_install ;;
		r) xtall_remove ;;
		*) print "Unknown action" ; exit 3
	esac

}

main "$@"

