#!/bin/sh

# this script assumes anything on the disk can be removed if corrupted
# other use cases may need different scripts.

# currently only supports ext4 but should be expanded

do_fsck()
{
	# preen
	/sbin/e2fsck -p $*
	EXIT_CODE=$?
	# exit code 1 is errors corrected
	[ "${EXIT_CODE}" -eq 1 ] && EXIT_CODE=0
	# exit code 2 or 3 means need to reboot
	[ "${EXIT_CODE}" -eq 2 -o "${EXIT_CODE}" -eq 3 ] && /sbin/reboot
	# exit code 4 or over is fatal
	[ "${EXIT_CODE}" -lt 4 ] && return "${EXIT_CODE}"

	# try harder
	/sbin/e2fsck -y $*
	# exit code 1 is errors corrected
	[ "${EXIT_CODE}" -eq 1 ] && EXIT_CODE=0
	# exit code 2 or 3 means need to reboot
	[ "${EXIT_CODE}" -eq 2 -o "${EXIT_CODE}" -eq 3 ] && /sbin/reboot
	# exit code 4 or over is fatal
	[ "${EXIT_CODE}" -ge 4 ] && printf "Filesystem unrecoverably corrupted, will reformat\n"

	return "${EXIT_CODE}"
}

do_fsck_extend_mount()
{
	DRIVE="$1"
	DATA="$2"

	do_fsck "$DATA" || return 1

	# only try to extend if there is a single partition and free space
	PARTITIONS=$(sfdisk -J "$DRIVE" | jq '.partitiontable.partitions | length')

	if [ "$PARTITIONS" -eq 1 ] && \
		sfdisk -F "$DRIVE" | grep -q 'Unpartitioned space' &&
		! sfdisk -F "$DRIVE" | grep -q '0 B, 0 bytes, 0 sectors'
	then
		SPACE=$(sfdisk -F "$DRIVE" | grep 'Unpartitioned space')
		printf "Resizing disk partition: $SPACE\n"

		# 83 is Linux partition id
		START=$(sfdisk -J "$DRIVE" | jq -e '.partitiontable.partitions | map(select(.type=="83")) | .[0].start')

		sfdisk -q --delete "$DRIVE" 2> /dev/null
		echo "${START},,83;" | sfdisk -q "$DRIVE"

		# set bootable flag
		sfdisk -A "$DRIVE" 1

		# update status
		blockdev --rereadpt $diskdev 2> /dev/null
		mdev -s

		# wait for device
		for i in $(seq 1 50); do test -b "$DATA" && break || sleep .1; mdev -s; done

		# resize2fs fails unless we use -f here
		do_fsck -f "$DATA" || return 1
		resize2fs "$DATA"

		do_fsck "$DATA" || return 1
	fi
}

do_mkfs()
{
	diskdev="$1"

	# new disks does not have an DOS signature in sector 0
	# this makes sfdisk complain. We can workaround this by letting
	# fdisk create that DOS signature, by just do a "w", a write.
	# http://bugs.alpinelinux.org/issues/145
	echo "w" | fdisk $diskdev >/dev/null

	# format one large partition
	echo ";" | sfdisk --quiet $diskdev

	# update status
	blockdev --rereadpt $diskdev 2> /dev/null

	# wait for device
	for i in $(seq 1 50); do test -b "$DATA" && break || sleep .1; mdev -s; done

	FSOPTS="-O resize_inode,has_journal,extent,huge_file,flex_bg,uninit_bg,64bit,dir_nlink,extra_isize"

	mkfs.ext4 -q -F $FSOPTS ${diskdev}1
}

# TODO fix for multiple disks, cdroms etc
DEV="$(find /dev -maxdepth 1 -type b ! -name 'loop*' | grep -v '[0-9]$' | sed 's@.*/dev/@@' | sort | head -1 )"

[ -z "${DEV}" ] && exit 1

DRIVE="/dev/${DEV}"

# see if it has a partition table already
if sfdisk -d "${DRIVE}" >/dev/null 2>/dev/null
then
	DATA=$(sfdisk -J "$DRIVE" | jq -e -r '.partitiontable.partitions | map(select(.type=="83")) | .[0].node')
	if [ $? -eq 0 ]
	then
		do_fsck_extend_mount "$DRIVE" "$DATA" || do_mkfs "$DRIVE"
	else
		do_mkfs "$DRIVE"
	fi
else
	do_mkfs "$DRIVE"
fi