#!/bin/sh -e

. /lib/rcscripts/sh/error.sh
. /lib/rcscripts/sh/files.sh

UUIDFILE=wsdd.uuid
UUIDFILE_DIR=/etc/ws/onvif/discovery
PERSISTENT_DIR=/lib/persistent
UUID_PREFIX=urn:uuid:
UUIDFILE_OWNER=wsdd

UUID_MAIN_FILE=$UUIDFILE_DIR/$UUIDFILE
UUID_BACKUP_FILE=$PERSISTENT_DIR$UUID_MAIN_FILE

STATIC_BACKUP_PREFIX=5581ad80-95b0-11e0-b883

# Rudimentary sanity check of the uuid file
# In case it gets created with the fallback mac 00408ccd0000
# it must be recreated
check_uuid_file() {
	local orguuid

	[ -f "$1" ] || return 1
	read orguuid <"$1" || return 1
	[ "${orguuid#*$UUID_PREFIX}" != "$orguuid" ] || return 1
	[ "${orguuid##*-}" != 00408ccd0000 ] || return 1
}

# Generates a new UUID with uuidgen -t (timestamp-mac mode)
# if that utility is available. Otherwise falls back to
# legacy mode (static_prefix-mac)
gen_uuid() {
	local _uuidgen serno prefix

	serno=$(bootblocktool -err -x SERNO) || error "No SERNO found"
	serno=$(echo $serno | tr A-F a-f)

	# Use a random prefix as fallback.
	prefix=$(cat /proc/sys/kernel/random/uuid || :)
	prefix=${prefix%-*}
	# Use a predefined prefix as a last resort.
	prefix=${prefix:-$STATIC_BACKUP_PREFIX}

	_uuidgen=$(command -v uuidgen 2>/dev/null || :)

	if [ "$_uuidgen" ]; then
		local tmp_prefix

		tmp_prefix=$($_uuidgen -t || :)
		# Strip away the macaddress portion
		# since it is most likely not correct anyway
		[ -z "$tmp_prefix" ] || prefix=${tmp_prefix%-*}
	elif [ $prefix = $STATIC_BACKUP_PREFIX ]; then
		warning "Using static UUID prefix"
	fi
	eval $1=\$prefix-\$serno
}

restore_uuid() {
	if check_uuid_file $UUID_BACKUP_FILE; then
		echo Restoring persistant device UUID
	else
		local uuid

		gen_uuid uuid
		echo Generated a new device UUID: $uuid
		echo $UUID_PREFIX$uuid > $UUID_BACKUP_FILE.tmp ||
			error "Failed to write $UUID_BACKUP_FILE.tmp"
		fsynced_write_or_cleanup $UUID_BACKUP_FILE.tmp $UUID_BACKUP_FILE
	fi

	cp -f $UUID_BACKUP_FILE $UUID_MAIN_FILE.tmp ||
		error "Failed to copy $UUID_BACKUP_FILE to $UUID_MAIN_FILE.tmp"
	fsynced_write_or_cleanup $UUID_MAIN_FILE.tmp $UUID_MAIN_FILE
}

save_uuid() {
	echo Saving device UUID to persistant storage
	cp -f $UUID_MAIN_FILE $UUID_BACKUP_FILE.tmp ||
		error "Failed to copy $UUID_MAIN_FILE to $UUID_BACKUP_FILE.tmp"
	fsynced_write_or_cleanup $UUID_BACKUP_FILE.tmp $UUID_BACKUP_FILE
}

# Make sure the persistent backup directory exist
[ -d "$PERSISTENT_DIR$UUIDFILE_DIR" ] ||
	mkdir -p $PERSISTENT_DIR$UUIDFILE_DIR ||
	error "Failed to create directory $PERSISTENT_DIR$UUIDFILE_DIR"

# Restore or generate a new uuid if it doesn't exist
if ! check_uuid_file "$UUID_MAIN_FILE"; then
	restore_uuid && exit 0
fi

# If the backup file doesn't exist save the one we have
if ! check_uuid_file "$UUID_BACKUP_FILE"; then
	save_uuid && exit 0
fi

# If the backup file exists but differs from the one we have
# override the backup.
read main <$UUID_MAIN_FILE || {
	save_uuid
	exit 0
}

read backup <$UUID_BACKUP_FILE || {
	save_uuid
	exit 0
}

[ "$main" = "$backup" ] && exit 0
save_uuid