#!/bin/sh
set -o errexit
set -o xtrace

# Return codes used in this script:
# 1: Current system is already mounted.
# 2: Offline system is already mounted.
# 3: fsck.ext2 returned code not equal to 0 (zero).

# Initialize Device Stack return variable.
# This shall be done as early as possible.

CLONE_STATUS_FILE=/opt/userdata/.clone-status
echo -n "started" > "${CLONE_STATUS_FILE}"

# Print date/timestamp in case of logging (for debugging purposes)
date

MMC_SYSTEM_A=$(cat /opt/extparam/system_A_root_blkdev)
MMC_SYSTEM_B=$(cat /opt/extparam/system_B_root_blkdev)

CURRENT_SYSTEM_DIR="/opt/fwu/system_current"
OFFLINE_SYSTEM_DIR="/opt/fwu/system_offline"

MMC_SYSTEM_OFFLINE=$(cat /opt/extparam/offline_root_blkdev)
MMC_SYSTEM_CURRENT=$(cat /opt/extparam/booted_root_blkdev)

FILESYSTEM_TYPE=ext3

finish()
{
  echo "executing cleanup trap"
  trap - INT TERM EXIT
  if [ "$(mount | grep -c "${CURRENT_SYSTEM_DIR}")" -gt 0 ]
  then
    umount "${CURRENT_SYSTEM_DIR}"
  fi
  if [ "$(mount | grep -c "${OFFLINE_SYSTEM_DIR}")" -gt 0 ]
  then
    umount "${OFFLINE_SYSTEM_DIR}"
  fi
}

trap finish INT TERM EXIT

echo "MMC_SYSTEM_A:${MMC_SYSTEM_A}"
echo "MMC_SYSTEM_B:${MMC_SYSTEM_B}"
echo "MMC_SYSTEM_CURRENT:${MMC_SYSTEM_CURRENT}"
echo "MMC_SYSTEM_OFFLINE:${MMC_SYSTEM_OFFLINE}"

# Ensure, that both mount points are unmounted.
# Unmount is done by trap and will not retried here.
[ "$(mount | grep -c "${CURRENT_SYSTEM_DIR}")" -gt 0 ] && echo "Current system is already mounted. Stopping." && exit 1
[ "$(mount | grep -c "${OFFLINE_SYSTEM_DIR}")" -gt 0 ] && echo "Offline system is already mounted. Stopping." && exit 2

CLONE_METHOD="cp"
#CLONE_METHOD="dd"
#CLONE_METHOD="none"

case "${CLONE_METHOD}" in
	cp)
		echo "Cloning via copy method."

		mkdir -p "${CURRENT_SYSTEM_DIR}"
		mount -t "${FILESYSTEM_TYPE}" -o ro "${MMC_SYSTEM_CURRENT}" "${CURRENT_SYSTEM_DIR}"

		# Erase the offline system.
		mkfs."${FILESYSTEM_TYPE}" -F "${MMC_SYSTEM_OFFLINE}"

		# Mount offline system writable.
		mkdir -p "${OFFLINE_SYSTEM_DIR}"
		mount -t "${FILESYSTEM_TYPE}" -o noatime,nodiratime "${MMC_SYSTEM_OFFLINE}" "${OFFLINE_SYSTEM_DIR}"

		# Copy the current system files to offline
		cd "${CURRENT_SYSTEM_DIR}"
		  cp -a . "${OFFLINE_SYSTEM_DIR}"
		cd -
		sync
		;;
	dd)
		echo "Cloning via dd method."

		# 4M is the preferred erase size of typical SD Cards.
		# As this is an eMMC we have a preferred erase size of 512k.
		dd if="${MMC_SYSTEM_CURRENT}" of="${MMC_SYSTEM_OFFLINE}" bs=512k
		sync
		;;
	*)
		echo "No clone method selected."
		;;
esac

umount "${CURRENT_SYSTEM_DIR}" || echo "Failed to unmount current system (${CURRENT_SYSTEM_DIR})."
umount "${OFFLINE_SYSTEM_DIR}" || echo "Failed to unmount offline system (${OFFLINE_SYSTEM_DIR})."

/sbin/fsck."${FILESYSTEM_TYPE}" -y "${MMC_SYSTEM_OFFLINE}"
EXIT_CODE=$?
if ! [ "${EXIT_CODE}" -eq 0 ]
then
  echo "Filesystemcheck returned non-zero (code: |${EXIT_CODE}|). Stopping."
  exit 3
fi

# Replace the bootscript if the md5sum is inconsistent, doesn't exist or differs from ours
# This equals a rollback when cloning over an invalidated system
echo "Checking installed bootscript..."
# The md5sum check respects the path from the .md5 file
cd /opt/extparam
  if md5sum -c boot.scr.md5 && diff -q boot.scr.md5 /opt/gira/default/boot/boot.scr.md5
  then
    echo "Bootscript is consistent and the correct version! Doing nothing."
  else
    echo "Replacing bootscript..."
    install -m 600 /opt/gira/default/boot/boot.scr /opt/extparam/boot.scr
    install -m 600 /opt/gira/default/boot/boot.scr.md5 /opt/extparam/boot.scr.md5
    sync
    echo "...done!"
  fi
cd -

echo -n "stopped" > "${CLONE_STATUS_FILE}"
echo "The clone script has successfully done it's job and will now exit with return code 0."
exit 0
