#!/bin/sh

## live-partial-squashfs-updates - Generate partial squashfs updates.
## Copyright (C) 2013 Richard Nelson <unixabg@gmail.com>
##
## This program comes with ABSOLUTELY NO WARRANTY; for details see COPYING.
## This is free software, and you are welcome to redistribute it
## under certain conditions; see COPYING for details.

set -e
#set -x

Cleanup_mounts () {
	echo "Unmounting the areas we created."
	for mount_point in "${_MOUNTLIST}"; do
		umount -l $mount_point
		rmdir $mount_point
	done
}

_MOUNTDIR=""
_MOUNTLIST="./filesystem_squashfs ./partial_squashfs_union ./partial_squashfs_updates"
_ROSTACK=":./filesystem_squashfs=ro"
for squash_file in $(ls ./psu-*.squashfs); do
	# Setup mount for the squashfs images.
	# Note that we stack here on the listing provided by ls command.
	_MOUNTDIR="$(basename $squash_file .squashfs)_squashfs"
	echo "Found $squash_file and setting up mount point of ${_MOUNTDIR}"
	if [ ! -d "${_MOUNTDIR}" ]; then
		mkdir "${_MOUNTDIR}"
	fi
	mount -o loop "./$squash_file" "./${_MOUNTDIR}"
	_ROSTACK=":./${_MOUNTDIR}=rr+wh${_ROSTACK}"
	_MOUNTLIST="${_MOUNTLIST} ./${_MOUNTDIR}"
done
echo "${_ROSTACK}"
echo "${_MOUNTLIST}"

# Setup mount for the filesystem.squashfs mount.
if [ ! -d "filesystem_squashfs" ]; then
	mkdir filesystem_squashfs
fi
mount -o loop ./filesystem.squashfs ./filesystem_squashfs

# Setup mount for the updates which we will squash later.
if [ ! -d "partial_squashfs_updates" ]; then
	mkdir partial_squashfs_updates
fi
mount -t tmpfs tmpfs ./partial_squashfs_updates

# Setup mount for the union where we stack ro squashfs and rw updates mount.
if [ ! -d "partial_squashfs_union" ]; then
	mkdir partial_squashfs_union
fi

_DEFAULTRUNTYPE="C"
echo "#############################################################"
echo "  (C)hroot - Chroot in to the filesystem.squashfs + psu-*.squashfs stack."
echo "  (J)oin   - Join the partial squashfs update files to new single psu-DATE.squashfs"
echo "  (N)ew    - New master filesystem.squashfs file which joins all *.squashfs file to new single filesystem.squashfs"
echo "Select run type (default is ${_DEFAULTRUNTYPE}):"

read _RUNTYPE

_RUNTYPE="${_RUNTYPE:-${_DEFAULTRUNTYPE}}"

if [ ${_RUNTYPE} = "C" ]
then
	#mount -t aufs -o br=./partial_squashfs_updates=rw:./filesystem_squashfs=ro none ./partial_squashfs_union
	mount -t aufs -o br=./partial_squashfs_updates=rw"${_ROSTACK}" none ./partial_squashfs_union
	echo "You selected to run a chroot"
	echo "Setup the chroot to union mount."
	echo "Mounting bindings for dev, proc, sys, pts in union."
	mount --bind /dev ./partial_squashfs_union/dev
	mount --bind /proc ./partial_squashfs_union/proc
	mount --bind /sys ./partial_squashfs_union/sys
	mount --bind /dev/pts ./partial_squashfs_union/dev/pts

	echo "Backup the union/etc/hosts."
	mv ./partial_squashfs_union/etc/hosts ./hosts.bak
	echo "Copying /etc/hosts to union/etc/hosts."
	cp /etc/hosts ./partial_squashfs_union/etc/hosts

	echo "Backup the union/etc/resolv.conf."
	mv ./partial_squashfs_union/etc/resolv.conf ./resolv.conf.bak
	echo "Copying /etc/resolv.conf to the union/etc/resolv.conf."
	cp /etc/resolv.conf ./partial_squashfs_union/etc/resolv.conf

	echo "Starting chroot in the union directory."
	chroot ./partial_squashfs_union /bin/bash

	echo "Exited the chroot so time to clean up."
	umount -l ./partial_squashfs_union/dev
	umount -l ./partial_squashfs_union/proc
	umount -l ./partial_squashfs_union/sys

	echo "Restore original union/etc/hosts."
	mv ./hosts.bak ./partial_squashfs_union/etc/hosts
	echo "Restore union/etc/resolv.conf."
	mv ./resolv.conf.bak ./partial_squashfs_union/etc/resolv.conf
	echo "Remove union/root/.bash_history."
	rm ./partial_squashfs_union/root/.bash_history

	# Prompt to save changes or not.
	_DEFAULTYESNO="N"
	echo "#############################################################"
	echo " (Y)es save my chroot modifications."
	echo " (N)o do not save my chroot modifications."
	echo "Select to save your chroot modifications (default is ${_DEFAULTYESNO}):
	"
	read _YESNO

	_YESNO="${_YESNO:-${_DEFAULTYESNO}}"

	if [ ${_YESNO} = "Y" ]
	then
		_DATE=$(date +%Y%m%d-%H%M%S)
		echo "Now making the updated squashfs ${_DATE}."
		mksquashfs ./partial_squashfs_updates psu-${_DATE}.squashfs

		# Since we use sed to put text at the top of the file make sure the file exists.
		if [ ! -e psu-changelog.txt ]
		then
			echo "Created changelog." >> psu-changelog.txt
		fi

		# Add entry to changelog for the psu file.
		echo "Please provide a small changelog entry for the psu-${_DATE}.squashfs :"
		read _NOTES
		sed -i "1s/^/${_DATE} - ${_NOTES}.\n/" psu-changelog.txt
	else
		echo "No chroot modifications saved to a psu file."
	fi

	Cleanup_mounts

elif [ ${_RUNTYPE} = "J" ] || [ ${_RUNTYPE} = "N" ]
then
	if [ ${_RUNTYPE} = "J" ]
	then
		# Modify the _ROSTACK to not include the filesystem_squashfs mount so we just stack the updates together
		_ROSTACK=$(echo ${_ROSTACK} | sed s@:./filesystem_squashfs=ro@@g)
		_ACTIONTYPE="join psu squashfs files to new single psu-DATE.squashfs"
	else
		_ACTIONTYPE="create a new single filesystem.squashfs"
	fi

	echo "${_ROSTACK}"
	#mount -t aufs -o br=./partial_squashfs_updates=rw:./filesystem_squashfs=ro none ./partial_squashfs_union
	mount -t aufs -o br=./partial_squashfs_updates=rw"${_ROSTACK}" none ./partial_squashfs_union

	# Prompt to join squashfs files or not.
	_DEFAULTYESNO="N"
	echo "#############################################################"
	echo " (Y)es, ${_ACTIONTYPE}."
	echo " (N)o, do not ${_ACTIONTYPE}."
	echo "Select to ${_ACTIONTYPE} (default is ${_DEFAULTYESNO}):
	"
	read _YESNO

	_YESNO="${_YESNO:-${_DEFAULTYESNO}}"

	if [ ${_YESNO} = "Y" ]
	then
		# Since we use sed to put text at the top of the file make sure the file exists.
		if [ ! -e psu-changelog.txt ]
		then
			echo "Created changelog." >> psu-changelog.txt
		fi

		_DATE=$(date +%Y%m%d-%H%M%S)

		if [ ${_RUNTYPE} = "N" ]
		then
			if [ ! -d "new_squashfs" ]; then
				mkdir new_squashfs
			fi
			echo "Now making a new and updated filesystem.squashfs."
			mksquashfs ./partial_squashfs_union ./new_squashfs/filesystem.squashfs
			# Add entry to changelog for the joining of the *.squashfs files to a new filesystem.squashfs.
			sed -i "1s/^/******* ${_DATE} - New filesystem.squashfs generated. ********\n/" psu-changelog.txt
		else
			echo "Now making the updated squashfs ${_DATE} from union."
			mksquashfs ./partial_squashfs_union psu-${_DATE}.squashfs
			# Add entry to changelog for the joining of the psu files.
			sed -i "1s/^/******* ${_DATE} - Joined squashfs files. ********\n/" psu-changelog.txt
		fi
	else
		echo "No psu files will be joined."
	fi

	Cleanup_mounts

	# Remove old directories and move old partials out.
	if [ ${_YESNO} = "Y" ]
	then
		if [ ! -d "partial_squashfs_updates-OLD-${_DATE}" ]; then
			mkdir psu-OOS-${_DATE}
		fi
		if [ ${_RUNTYPE} = "N" ]
		then
			rsync -av --remove-source-files ./psu-*.squashfs ./psu-OOS-${_DATE}/
			rsync -av --remove-source-files ./filesystem.squashfs ./psu-OOS-${_DATE}/
			rsync -av --remove-source-files ./new_squashfs/filesystem.squashfs ./
			rmdir ./new_squashfs
		else
			rsync -av --remove-source-files --exclude psu-${_DATE}.squashfs ./psu-*.squashfs ./psu-OOS-${_DATE}/
		fi
	else
		echo "No rsync of current partials to an Out Of Service folder will occur."
	fi
else
	echo "You entered an unknowon choice!"
	echo "Aborting."
	Cleanup_mounts
	exit 1
fi

echo "All done goodbye!"
exit 0
