#!/bin/sh

# Convert a ddrescue log file into text suitable for dmsetup create to
# help with recovery.
#
# Licensed under GPL2.
#
# Written by William Thompson 2017

DEV=$1
BBT=$2

if [ -z "$DEV" ];then
	echo "Usage: $0 <device> [bbt]"
	echo " or  : $0 <device> [bbt] < ddrescue.log"
	echo
	echo "device	Backing device for linear target.  Does not have to exist."
	echo "		A real device must be available before dmsetup will work."
	echo "bbt	Bad block target.  Must be either error or zero."
	echo "		Default is error."
	exit 1
fi

case "$BBT" in
	"")
		BBT=error
		;;
	error | zero)
		;;
	*)	echo "Bad Block target must be error or zero"
		exit 1
		;;
esac

if [ -t 0 ];then
	echo "Paste a ddrescue log file here and it will be converted to"
	echo "a device mapper target."
	echo "Press ^C to cancel or ^D to finish."
fi

unset table
untried=0
nextstart=0
while read start length status junk;do
	case "$start" in
		0x*)	start=$(($start)) ;;
		\#*)	continue ;;
		*)	echo "Start must be a hex number beginning with 0x"
			exit 1
			;;
	esac
	case "$length" in
		# Status line
		"?" | "*" | / | - | F | G | +)
			continue
			;;
		0x*)	length=$(($length)) ;;
		*)	echo "Length must be a hex number beginning with 0x"
			exit 1
			;;
	esac
	if [ "$(($start & 511))" -gt 0 ];then
		echo "Start is not a multiple of 512, aborting"
		exit 1
	fi
	if [ "$(($length & 511))" -gt 0 ];then
		echo "Length is not a multiple of 512, aborting"
		exit 1
	fi
	if [ "$start" != "$nextstart" ];then
		echo "Exected start of $nextstart, got $start, aborting"
		exit 1
	fi
	nextstart=$(($start + $length))
	start=$(($start >> 9))
	length=$(($length >> 9))
	if [ "$untried" = 1 ];then
		echo "An untried region exists and is not the last, aborting"
		exit 1
	fi
	target=bad
	case "$status" in
		"*" | "/" )
			echo "A non-trimmed/non-scraped/non-split block detected, converting to $BBT"
			target=$BBT
			;;
		"-")	target=$BBT
			;;
		"+")	table="$table$start $length linear $DEV $start
"
			continue
			;;
		"?")	untried=1
			target=zero
			continue
			;;
	esac
	table="$table$start $length $target
"
done

echo "$table"
