#! /usr/bin/env bash
#
# cfatsn: change FAT serial number
#
# Change serial number of FAT partition
#
# Release: 1.0 of 2019/01/29
# Licence: WTFPL - www.wtfpl.net
# 2019, Joseph Maillardet

function info { printf '%b\n' "$1"; }
function error { usage; >&2 info "Error: $1"; [ -z "$2" ] || exit "$2"; }

# Usage
function usage {
	cat <<-EOF
		Usage: $(basename "$0") [-F {16|32}] -d {partition_device} -s {serial_number}
		where:
		    partition_device = the partition device (like /dev/sda1 or /dev/nvme0n1p3)
		       serial_number = the serial number to use (like 5286-06FF or A1C0-B378)
	EOF
}

# Dash options checking
OPTS=$(getopt -o F:d:s:h --long fat:,device:,serial:,help -n "$(basename "$0")" -- "$@") \
        || error "getopt failed with error code: $?" 1
eval set -- "$OPTS"

fat=''; offset=''; device=''; serial=''

while true; do
        case "$1" in
                -F|--fat) fat="$2"; shift 1 ;;
                -d|--device) device="$2"; shift 2 ;;
                -s|--serial) serial="$2"; shift 2 ;;
                -h|--help|h|help) usage; shift ;;
                --) shift; break ;;
                *) break ;;
        esac
done

[ -z "$fat" ] && fat="32"
if [ "$fat" == "16" ]; then
	offset=39
elif [ "$fat" == "32" ]; then
	offset=67
else
	error "Unknown FAT format" 1
fi

[ -z "$(echo $device | grep '^/dev/.')" ] && error 'Need a device' 2
[ -z "$(echo $serial | grep -E '^[0-9A-Z]{4}-[0-9A-Z]{4}$')" ] && error 'Need a serial number' 3

printf "Going to modify FAT$fat partition: $device with serial: $serial\n"

read -p 'Ok (Y/n)?: ' ask
case "$ask" in
	[Yy]|[Yy][Ee][Ss]) go=true ;;
	'') go=true ;;
	*) go=false ;;
esac

if $go; then
	info "Let's go..."
	printf "\x${serial:7:2}\x${serial:5:2}\x${serial:2:2}\x${serial:0:2}" |\
	dd bs=1 seek="$offset" count=4 conv=notrunc of="$device"
	info "Done."
else
	info "Nothing to do. Bye."
fi

exit 0