#!/bin/ksh -p
#
# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#ident	"@(#)create_archive.ksh	1.3	07/09/30 SMI"
#

VERSION="1.3"

bname=`basename $0`

usage()
{
	print -u2 "Usage:\n"
	print -u2 "$bname [ -R <alt_root> ] -o <output_file>"
	print -u2 "\t[ -x <exclude_pattern> ] [ -X <exclude_pattern_file> ]\n"
	print -u2 "$bname [ -R <alt_root> ] -p <output_dir>"
	print -u2 "\t[ -x <exclude_pattern> ] [ -X <exclude_pattern_file> ]\n"

	print -u2 "Where:"
	print -u2 "\t-R\tAlternate Root to archive (default is \"/\").\n"

	print -u2 "\t-x\t'/usr/xpg4/bin/grep -E' (full regular expression)"
	print -u2 "\t  \tpattern for file paths to exclude from the archive."
	print -u2 "\t\t(Multiple -x is permitted)"
	print -u2 "\t\tExample: -x \"^export/app1/\"\n"

	print -u2 "\t-X\tFile containing '/usr/xpg4/bin/grep -E' (full regular "
	print -u2 "\t  \texpression) patterns for file paths to exclude from "
	print -u2 "\t  \tthe archive"
	print -u2 "\t\t(Multiple -X is permitted)\n"

	print -u2 "\t-o\tAbsolute path of output file.\n"

	print -u2 "\t-p\tAbsolute path of output directory.\n"

	print -u2 "\t-V\tPrint version.\n"
}

ROOT=/
OUTFILE=""
EXCLUDELIST=""
EXCLUDEFILE=""
EXCLUDEARGS=""
while getopts "R:x:X:o:p:V" opt ; do
	case $opt in
	R)	ROOT=$OPTARG
		;;
	x)	EXCLUDELIST="$EXCLUDELIST $OPTARG"
		;;
	X)	EXCLUDEFILE="$EXCLUDEFILE $OPTARG"
		;;
	o)	OUTFILE=$OPTARG
		;;
	p)	PASSTHRUDIR=$OPTARG
		;;
	V)	echo $VERSION
		exit 0;;
	?)	usage
		exit 2
		;;
	esac
done

id=`/usr/xpg4/bin/id -u`
if [[ "$id" != "0" ]] ; then
	print -u2 "Error: Must be root."
	usage
	exit 1
fi

# Validate root
if [[ $ROOT != /* ]] ; then
	print -u2 "Error: \"$ROOT\" must be an absolute path"
	usage
	exit 1
fi
[[ $ROOT != */ ]] && ROOT=$ROOT/

if [[ ! -d $ROOT ]] ; then
	print -u2 "Error: \"$ROOT\" must be a directory."
	usage
	exit 1
fi

# Validate output file / directory
if [[ $OUTFILE = "" && $PASSTHRUDIR = "" ]] ; then
	print -u2 "Error: -o <output_file> or -p <output_dir> required."
	usage
	exit 1
fi
if [[ $OUTFILE != "" && $PASSTHRUDIR != "" ]] ; then
	print -u2 "Error: only one of -o and -p are permitted."
	usage
	exit 1
fi

if [[ -n $OUTFILE && $OUTFILE != /* ]] ; then
	print -u2 "Error: <output_file> must be an absolute path."
	usage
	exit 1
fi
if [[ -n $PASSTHRUDIR && $PASSTHRUDIR != /* ]] ; then
	print -u2 "Error: <output_dir> must be an absolute path."
	usage
	exit 1
fi

if [[ -n $OUTFILE ]]; then
	OUTDIR=`dirname $OUTFILE`
	OUTFILE=`basename $OUTFILE`
	if [[ ! -d $OUTDIR || ! -w $OUTDIR ]] ; then
		print -u2 "Error:  Cannot create output file.  Directory does not " \
		    "exist or is not writeable."
		usage
		exit 1
	fi
	integer i=0
	TMPFILE=$OUTFILE.s8.$$.$i
	while [[ -a $OUTDIR/$TMPFILE ]] ; do
		(( i = i + 1 ))
		TMPFILE=$OUTFILE.s8.$$.$i
	done

	trap "/usr/bin/rm -f $OUTDIR/$TMPFILE ; exit 1" 0 1 2 15
	touch $OUTDIR/$TMPFILE
	if (( $? != 0 )) ; then
		print -u2 "Error, would not write output file."
		usage
		exit 1
	fi
fi

for f in $EXCLUDEFILE ; do
	[[ $f != /* ]] && f=${ROOT}$f
	if [[ ! -f $f || ! -r $f ]] ; then
		print -u2 "Error: \"$f\" must be a readable file."
		usage
		exit 1
	fi
	EXCLUDEARGS="$EXCLUDEARGS -f $f"
done

if [[ -n $OUTFILE ]]; then
	EXCLUDEARGS="-e $TMPFILE$"
fi
if [[ -n $PASSTHRUDIR ]]; then
	EXCLUDEARGS="-e $PASSTHRUDIR$"
fi

#
# Automatically exclude files that are not persistent
#
for f in $EXCLUDELIST '^etc/mnttab$' '^var/run$' '^var/run/' ; do
	EXCLUDEARGS="$EXCLUDEARGS -e $f"
done

cd $ROOT
if [ $? != 0 ]; then
	print -u 2 "Error: Could not change directory to root dir '$ROOT'"
	exit 1
fi

list=`echo !(proc|dev|devices|tmp)`

if [[ -n $OUTFILE ]]; then
	find $list ! -local -prune \
	    -o \( -type d -o -type f -o -type l \) -print |
    	    /usr/xpg4/bin/grep -E -v $EXCLUDEARGS | cpio -oc -O $OUTDIR/$TMPFILE
else
	find $list ! -local -prune \
	    -o \( -type d -o -type f -o -type l \) -print |
    	    /usr/xpg4/bin/grep -E -v $EXCLUDEARGS | cpio -pdm $PASSTHRUDIR
fi

if (( $? != 0 )) ; then
	print -u2 "Error: creating archive failed."
	exit 1
fi

if [[ -n $OUTFILE ]]; then
	mv $OUTDIR/$TMPFILE $OUTDIR/$OUTFILE
fi

exit 0

