#!/bin/sh
#vim:filetype=sh
#vim:shiftwidth=8

set -e
echo -n "$0: "

if [ -z "$MOUNTPOINT" ] ; then
	MOUNTPOINT=/mnt/unionfs
fi
if [ -z "$LOWER_DIR" ] ; then
	LOWER_DIR=/n/lower
fi
if [ -z "$NFS" ] ; then
	NFS=
fi
if [ -z "$DEBUG" ] ; then
	DEBUG=0
fi
MOUNTS=0

function roloopify {
	local DIR=$1
	if [ ! -d "$DIR" ] ; then
		echo "Can not find $DIR" 1>&2
		return 1
	fi
	mkisofs -quiet -o /tmp/$$.iso -JR $DIR
	mount -o loop,ro /tmp/$$.iso $DIR
#	rm -f /tmp/$$.iso
	echo "Inspect"
	read N
	return 0
}

function havechattr {
	local FILE=tmp.chattr.check
	if [ ! -d $1 ] ; then
		return 1
	fi
	touch $1/$FILE
	if ! chattr +i $1/$FILE >/dev/null 2>&1 ; then
		rm -f $1/$FILE
		return 1
	fi
	if (echo "Hello World" > $1/$FILE) >/dev/null 2>&1 ; then
		chattr -i $1/$FILE >/dev/null 2>&1
		rm -f $1/$FILE
		return 1
	fi
	chattr -i $1/$FILE
	rm -f $1/$FILE
	return 0
}

function create_hierarchy {
	touch $LOWER_DIR/f
	if havechattr $LOWER_DIR ; then
		chattr -R -i $LOWER_DIR/*
	fi
        rm -rf $LOWER_DIR/*

        while read LINE
        do
                if [ "$LINE" = "" ] ; then
                    continue
                fi
                TYPE=`echo $LINE | cut -d' ' -f 1`
                NAME=`echo $LINE | cut -d' ' -f 2`

		unset DIR FILE IMMUTABLE SOURCE	SYMLINK

		( echo $TYPE | grep -q d ) && DIR=1
		( echo $TYPE | grep -q f ) && FILE=1
		( echo $TYPE | grep -q i ) && IMMUTABLE=1
		( echo $TYPE | grep -q s ) && SOURCE=1
		( echo $TYPE | grep -q l ) && SYMLINK=1

		if [ ! -z "$SOURCE" ] ; then
			if [ ! -z "$DIR" ] ; then
				echo "BAD TYPE (rename sources cannot be directories): $TYPE" 1>&2
				exit 1
			fi
			FILE=1
		fi

		if [ ! -z "$IMMUTABLE" ] ; then
			if [ -z "$DIR" -a -z "$SYMLINK" ] ; then
				FILE=1
			fi
		fi

		if [ ! -z "$DIR" -a ! -z "$FILE" ] ; then
			echo "BAD TYPE (both a file and directory) : $TYPE" 1>&2
			exit 1
		fi
		if [ ! -z "$DIR" -a ! -z "$SYMLINK" ] ; then
			echo "BAD TYPE (both a symbolic link and directory) : $TYPE" 1>&2
			exit 1
		fi
		if [ ! -z "$FILE" -a ! -z "$SYMLINK" ] ; then
			echo "BAD TYPE (both a symbolic link and a file) : $TYPE" 1>&2
			exit 1
		fi


		if [ ! -z "$DIR" -a ! -z "$SOURCE" ] ; then
			echo "Directories can not be sources: $TYPE" 1>&2
			exit 1
		fi

		if [ ! -z "$SYMLINK" -a ! -z "$SOURCE" ] ; then
			echo "Symbolic links can not be sources: $TYPE" 1>&2
			exit 1
		fi

                if [ ! -z "$DIR" ] ; then
                        mkdir -p $NAME
                elif [ ! -z "$FILE" ] ; then
                        mkdir -p `dirname $NAME` || exit $?
			if [ ! -z "$SOURCE" ] ; then
				echo "Source file." > $NAME || exit $?
			else
				echo $NAME > $NAME || exit $?
			fi
                elif [ ! -z "$SYMLINK" ] ; then
			ln -s "linktext:$NAME" $NAME
		else
			echo "What type am i: $TYPE" 1>&2
			exit $?
		fi

                if [ ! -z "$IMMUTABLE" ] ; then
			chattr +i $NAME || exit $?
		fi
        done
}

function check_hierarchy {
        ( find $1 -type d -printf 'd %p\n' ; find $1 -type f -printf 'f %p\n' ; find $1 -type b -printf 'b %p\n' ; find $1 -type c -printf 'c %p\n' ; find $1 -type l -printf 'l %p\n') | sort > /tmp/check-$$
        grep -v '^$' | sort | diff -u - /tmp/check-$$
        ERR=$?
        rm -f /tmp/check-$$
        return $ERR
}

function mount_union {
	if [ "$MOUNTS" -gt 0 ] ; then
		echo "There is already an outstanding mount!" 1>&2
		exit 1
	fi

        if [ -z "$1" ] ; then
                OPTION="debug=$DEBUG,dirs="
        else
                OPTION="$1,debug=$DEBUG,dirs="
        fi

        shift

        while [ "$#" -gt 0 ]
        do
                OPTION="$OPTION$1"
                if [ "$#" -ne "1" ] ; then
                        OPTION="$OPTION"":"
                fi
                shift
        done

        mount -t unionfs -o $OPTION none $MOUNTPOINT

	MOUNTS=$((MOUNTS + 1))

        return $?
}

function unmount_union {
	umount $MOUNTPOINT
	ERR=$?
	if [ "$?" -eq "0" ] ; then
		MOUNTS=$((MOUNTS - 1))
	else
		echo "Could not unmount $MOUNTPOINT" 1>&2
		exit 1
	fi
	return $ERR
}

function checktype {
    local F=$1
    local CHECK=$2

    local ERR=
    if [ "$CHECK" = "-" ] ; then
        [ ! -e "$F" ] || ERR=$?
    elif [ "$CHECK" = "f" ] ; then
        [ -f "$F" ] || ERR=$?
    elif [ "$CHECK" = "d" ] ; then
        [ -d "$F" ] || ERR=$?
    elif [ "$CHECK" = "b" ] ; then
        [ -b "$F" ] || ERR=$?
    elif [ "$CHECK" = "c" ] ; then
        [ -c "$F" ] || ERR=$?
    elif [ "$CHECK" = "l" ] ; then
        [ -l "$F" ] || ERR=$?
    else
        echo "Unknown check '$CHECK'" 1>&2
        /bin/false
    fi
    local SERR=$?
    if [ -z "$ERR" ] ; then
	ERR=$SERR
    fi

    if [ "$ERR" != "0" ] ; then
        echo "$F doesn't match '$CHECK'" 1>&2
        ls -ld $F 1>&2
    fi

    return $ERR
}

function checkperms {
	local F=$1
	local CHECK=$2

	local PERMS=`find "$1" -printf %m`

	if [ "$PERMS" != "$CHECK" ] ; then
		echo "$F permissions $PERMS doesn't match '$CHECK'" 1>&2
		ls -ld $F 1>&2
		return 1
	fi

	return 0
}

function shouldfail {
	if $* 2>/tmp/saveout-$$ ; then
		echo "UNWANTED SUCCESS: " $*
		cat /tmp/saveout-$$
		return 1
	fi
	rm -f /tmp/saveout-$$
	return 0
}

function complete_test {
	if [ "$MOUNTS" -gt 0 ] ; then
		echo "There is a leftover mount!" 1>&2
		exit 1
	fi
	if [ -f complete.sh ] ; then
		COMPLETE=1
		source complete.sh
	fi
	echo "OK"
	exit 0
}

function start_test {
	if [ -f start.sh ] ; then
		START=1
		source start.sh
		START=
	fi
}

start_test
