#!/bin/dash
# James Budiono 2011, 2013, 2014, 2016, 2022
# sb2dir.sh - sandbox to directory
# copy contents of sandbox to dir, removing all known sandboxing files

SANDBOX_ROOT=/mnt/sb/sandbox
TARGET_ROOT=/tmp
FILTER=clear_std # default

### helpers ###

usage() {
	cat << EOF
Usage: ${0##*/} [options] dirname [sandbox-id]
Extracts content of sandbox into $TARGET_ROOT/\$dirname directory.

If dirname starts with /, then it is copied to \$dirname instead.
If sandbox-id is not specified, the default sandbox $SANDBOX_ROOT is used.
If sandbox-id is specified, sandbox ${SANDBOX_ROOT}.sandbox-id is used instead.
if sandbox-id starts with /, then it is taken as a path and used as is.

options:
--clear-none : don't delete anything
--clear-aufs : remove only aufs whiteouts
--clear-std  : remove files created by standard sandbox too (default)
--clear-lxc  : remove files created by lxc sandbox too

EOF
	exit 1
}


### filters ###

clear_none() {
	cat
}

clear_aufs() {
	sed -ne '
# remove all the whiteout files
\_.wh._ d
p'
}

clear_std() {
	clear_aufs | sed -ne '
# sandbox created stuff and bash history
\_/etc/\.XLOADED$_ d
\_/etc/BOOTSTATE$_ d
\_/etc/profile$_ d
\_/etc/shinit$_ d
\_/usr/bin/xwin$_ d
\_/usr/bin/wmexit$_ d
\_/root/\.Xauthority$_ d
\_/root/\.history$_ d
\_/root/\.bash\_history$_ d
p'
}

clear_lxc() {
	clear_aufs | clear_std | sed -ne '
# and sandbox-lxc created stuff
\_/etc/rc\.d/rc\.sysinit\.lxc$_ d
\_/etc/rc\.d/rc\.shutdown\.lxc$_ d
\_/etc/rc\.d/rc\.network\.lxc$_ d
\_/etc/rc\.d/rc\.oneshot$_ d
\_/etc/X11/host-X11$_ d
\_/etc/hosts$_ d
\_/etc/hostname$_ d
\_/etc/inittab$_ d
\_/etc/netparams$_ d
\_/sbin/init$_ d
\_/sbin/poweroff$_ d
\_/sbin/reboot$_ d
\_/var/run/utmp$_ d
\_/var/run/wtmp$_ d
\_/dev/lxc/_ d; \_/dev/fd$_ d
\_/dev/console$_ d; \_/dev/stdin$_ d; \_/dev/stdout$_ d; \_/dev/stderr$_ d
\_/dev/full$_ d; \_/dev/null$_ d; \_/dev/zero$_ d
\_/dev/ptmx$_ d; \_/dev/random$_ d; \_/dev/urandom$_ d
\_/dev/tty$_ d; \_/dev/tty1$_ d; \_/dev/tty2$_ d; \_/dev/tty3$_ d; \_/dev/tty4$_ d;
p'
}

### main ###

# option processing
while [ "$1" ]; do
	case "$1" in
		--help|-h)
			usage ;;
			
		# filters
		--clear-none) FILTER=clear_none ;;
		--clear-aufs) FILTER=clear_aufs ;;
		--clear-std)  FILTER=clear_std ;;		
		--clear-lxc)  FILTER=clear_lxc ;;

		*)
			if [ -z "$TARGET" ]; then
				TARGET="$1"
			else
				SOURCE="$1"
			fi ;;
	esac
	shift
done
[ -z "$TARGET" ] && usage

# post-process source and targets
case "$TARGET" in
	# start with a slash - use as is
	/*) ;;
	# not start with a slash - append TARGET_ROOT
	*)  TARGET=$TARGET_ROOT/$TARGET ;; 
esac

case "$SOURCE" in
	# empty - use sandbox root as is
	"") SOURCE=${SANDBOX_ROOT} ;; 
	# start with a slash - use as is
	/*) ;;
	# not start with a slash - append SANDBOX_ROOT
	*)  SOURCE=${SANDBOX_ROOT}.${SOURCE} ;; 
esac

# sanity check
if [ -e "$TARGET" ]; then
	echo $TARGET already exist. Delete it first, or choose another dirname.
	exit 1
fi

# do copy
echo "Copying to $TARGET from $SOURCE using $FILTER"
mkdir -p "$TARGET"
cd "$SOURCE"
find . | $FILTER | cpio -d -p "$TARGET"

# delete all empty directories
cd "$TARGET"
find . -type d -empty -delete

# don't create if sandbox is completely empty
if rmdir $TARGET 2> /dev/null; then # if dir is empty then this will delete it
	echo Sandbox contains nothing.
else
	echo Output in $TARGET
fi
