#!/bin/bash
##
#  Korinf project
#
#  Local chroot mount related functions
#
#  Copyright (c) Etersoft <http://etersoft.ru> 2005, 2006, 2007, 2009
#  Copyright (c) Vitaly Lipatov <lav@etersoft.ru> 2009
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU Affero General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.

#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Affero General Public License for more details.

#  You should have received a copy of the GNU Affero General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
##


MOUNT_MODULE_INCLUDED=1

mount_linux()
{
	local dist=$1
	if is_remote_build $dist ; then
		rhost=$(get_remote_host $dist)
		if [ "$rhost" = "docker" ] ; then
			#if a='' docker ps --all --format "{{.Names}}" | grep "^$(get_docker_image)$" ; then
			#	return
			#fi
			echo "Create docker build system:" >&2
			a='' docker build -f $KORINFETC/docker/$dist/Dockerfile -t $(get_docker_image $dist) . #|| return 1
# --rm
			a='' docker run -d --name $(get_docker_container $dist) $(get_docker_image $dist)
			a='' docker start $(get_docker_container $dist)
return 0
		fi
		return
	fi

	local MOUNTPARAM

	# Note!
	BUILDERHOME=$2

	assert_var CHROOTDIR LOCUSER

	# x86_64/Debian/6.0 -> x86_64-Debian-6.0
	BUILDROOT=`mktemp -d $CHROOTDIR/${dist//\//-}-XXXXXX`
	# Создаём необходимые каталоги
	mkdir -p $CHROOTDIR
	$SUDO chown $LOCUSER $CHROOTDIR

	# Note! Define and create BUILDHOME here
	if [ -z "$BUILDERHOME" ] ; then
		# create temp home
		BUILDERHOME=$BUILDROOT-home
		mkdir -p $BUILDERHOME/{,tmp,RPM,RPM/BUILD,RPM/RPMS} || fatal "Can't create $BUILDERHOME"
		chmod g+rwx $BUILDERHOME
		$SUDO chown $LOCUSER $BUILDERHOME -R
	fi

	# FIXME: why LOCUSER??
	chmod g+rwx $BUILDROOT
	$SUDO chown $LOCUSER $BUILDROOT -R

	[ -z "$BUILDROOT" ] && echo "Skip mount due empty BUILDROOT" && return 1
	echo "Mount $LOCALLINUXFARM/$dist to $BUILDROOT (user $INTUSER)..."

	# FIXME:
	[ -d $LOCALLINUXFARM ] && MOUNTPARAM="--bind" || MOUNTPARAM="-o soft"
	$SUDO mount $LOCALLINUXFARM/$dist $BUILDROOT $MOUNTPARAM || { warning "Cannot mount..." ; return 1 ; }
	$SUDO chmod o+rx $BUILDROOT
	#ls -l $BUILDROOT
	test -d $BUILDROOT/etc/ || fatal "Linux system is missed in $BUILDROOT"

	# TODO: need create these dir as root!
	# $BUILDROOT/run
	$SUDO su $LOCUSER -c "mkdir -p $BUILDROOT/proc $BUILDROOT/sys $BUILDROOT/tmp $BUILDROOT/home $BUILDROOT/home/$INTUSER $BUILDROOT/srv/wine"
	$SUDO mount -t proc proc $BUILDROOT/proc || { warning "Cannot mount /proc" ; return 1 ; }
	$SUDO mount -t sysfs none $BUILDROOT/sys || { warning "Cannot mount /sys" ; return 1 ; }
	#$SUDO mount $BUILDROOT $BUILDROOT/sys || { warning "Cannot mount /sys" ; return 1 ; }
	$SUDO mount -t devpts none $BUILDROOT/dev/pts -o nosuid,noexec,gid=tty,mode=620 || { warning "Cannot mount /sys" ; return 1 ; }

	if [ -d "$BUILDROOT/dev/shm" ] ; then
		$SUDO mount -t tmpfs shmfs $BUILDROOT/dev/shm || { warning "Cannot mount /dev/shm" ; return 1 ; }
	fi

	echo "Mount home $BUILDERHOME ..."
	$SUDO mount $BUILDERHOME $BUILDROOT/home/$INTUSER --bind || { warning "Cannot mount home" ; return 1 ; }

	echo "Mount /tmp $BUILDROOT-tmp ..."
	mkdir -p $BUILDROOT-tmp
	# TODO: not allowed in sudo
	#$SUDO chown root:root $BUILDROOT-tmp
	$SUDO chmod 01777 $BUILDROOT-tmp
	$SUDO mount $BUILDROOT-tmp $BUILDROOT/tmp --bind || { warning "Cannot mount /tmp" ; return 1 ; }

	#echo Mount srv/wine...
	#$SUDO mount /net/wine $BUILD/srv/wine --bind || { warning "Cannot mount home" ; return 0 ; }
}

terminate_using()
{
	local u
	local LISTPROC
	u=$1
	$SUDO fuser -vk $u
	LISTPROC=`$SUDO su $LOCUSER -c "/usr/sbin/lsof | grep $u | awk '{print \\$2}' | sort -u"`
	echo "Kill process use our dir (f.i. gpg-agent): $LISTPROC"
	$SUDO su $LOCUSER -c "echo $LISTPROC | xargs kill"
}

end_umount()
{
	local dist=$1
	local i u ERR
	ERR=0

	# if early error
	[ -z "$DISTRNAME" ] && return

	if is_remote_build $dist ; then
		rhost=$(get_remote_host $dist)
		if [ "$rhost" = "docker" ] ; then
			echo "Remove docker build system:" >&2
			a= docker stop -t1 $(get_docker_container $dist) || return 1
			#a= docker destroy $(get_docker_container) || return 1
			#a= docker rmi --no-prune $(get_docker_image) || return 1
		fi
		return $ERR
	fi

	if [ -z "$BUILDROOT" ] ; then
		[ -z "$ADEBUG" ] || echo "Skip umount due empty BUILDROOT"
		return 1
	fi

	echo "Unmounting and cleaning $BUILDROOT..."
	for i in /proc/bus/usb /proc/sys/fs/binfmt_misc /proc /sys /run /home/$INTUSER /dev/shm /dev/pts /tmp / ; do
		u=$BUILDROOT$i
		if [ -d $u ] && mount | grep $i >/dev/null ; then
			if ! $SUDO umount $u ; then
				terminate_using $u
				sleep 1
				$SUDO umount -v $u || terminate_using $u
			fi
			#|| echo "Failed $u umount"
			#$SUDO umount $i || $SUDO umount $i -l || ERR=1
		fi
	done
	[ $ERR = 0 ] && echo "DONE" || echo "Umount FAILED"
	if [ -z "$ADEBUG" ] ; then
		if echo $BUILDERHOME | grep -q $BUILDROOT ; then
			echo "Removing $BUILDERHOME ..."
			#$SUDO su $LOCUSER -c "rm -rf $BUILDERHOME" || ERR=1
			$SUDO su $LOCUSER -c "rm -rf $BUILDERHOME" || sleep 2 || $SUDO su $LOCUSER -c "rm -rf $BUILDERHOME" || (echo $(fuser $BUILDERHOME) && ERR=1)
			TMPBUILDERHOME=
		fi
		echo "Removing $BUILDROOT ..."
		#$SUDO su $LOCUSER -c "rmdir -v $BUILDROOT" || ERR=1
		$SUDO su $LOCUSER -c "rmdir -v $BUILDROOT" || sleep 2 || $SUDO su $LOCUSER -c "rmdir -v $BUILDROOT" || (echo $(fuser $BUILDERROOT) &&  ERR=1)
		[ $ERR = 0 ] && echo "DONE" || echo "Removing FAILED"
	else
		echo "Skip removing due ADEBUG set"
	fi
	BUILDROOT=""
	return $ERR
}

# run command for dist
# use --user for change to local user INTUSER
run_in_chroot()
{
	assert_var INTUSER

	local LOUSER=""
	if [ "$1" = "--user" ] ; then
		LOUSER=$INTUSER
		shift
	else
		# FIXME
		LOUSER=root
	fi

    local INTERACTIVE="-i"
    [ "$1" = "--interactive" ] && INTERACTIVE="-ti" && shift

	# run via ssh if remote build system
	local rhost rcommands
	rhost=$(get_remote_host $dist)
	if [ -n "$rhost" ] ; then
		assert_var dist
		if [ "$rhost" = "docker" ] ; then
			echo "Run command in docker build system:" >&2
			if [ -z "$LOUSER" ] || [ "$LOUSER" = "root" ] ; then
				#evz exec $DISTRNAME/$DISTRVERSION "$@"
				echo "# $@" >&2
				a='' docker exec $INTERACTIVE -e LC_ALL=C $(get_docker_container $dist) sh -c "$*"
			else
				#evz exec $DISTRNAME/$DISTRVERSION "gosu $INTUSER export LANG=C ; export LC_ALL=C ; . ~/.profile ; $@"
				echo "$ $@" >&2
				a='' docker exec $INTERACTIVE --user $INTUSER -e LC_ALL=C $(get_docker_container $dist) sh -c "$*"
			fi
			return
		fi
		rcommands=`eval echo $(get_remote_commands $dist)`
		# do not use command for a user
		#[ -n "$LOUSER" ] || rcommands=
		# Note: this output can be write to file with redirect output
		echo "Run command in remote ($rhost) build system:" >&2
		# FIXME: add -t if need interactive
		if [ -z "$LOUSER" ] || [ "$LOUSER" = "root" ] ; then
		    #ssh -i $PRIVATESSHKEY $INTUSER@$rhost $rcommands "\"export LANG=C ; export LC_ALL=C ; $@\""
			echo "# $@" >&2
		    ssh -i $PRIVATESSHKEY $INTUSER@$rhost $rcommands "\"$@\""
		else
			echo "$ $@" >&2
		    ssh -i $PRIVATESSHKEY $INTUSER@$rhost "export LANG=C ; export LC_ALL=C ; . ~/.profile ; $@"
		fi
		return
	fi

	echo "Run command in chrooted build system:" >&2
	echo "# $@" >&2
	assert_var BUILDARCH BUILDROOT
	PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin $NICE setarch $BUILDARCH $SUDO chroot $BUILDROOT \
		su - $LOUSER -c "export LANG=C ; export LC_ALL=C ; $@"
	# TODO: use -s instead -c: https://bugzilla.redhat.com/show_bug.cgi?id=186879
}
