#!/bin/sh

# For [/dev/disk/by-id/]dm-uuid-?*|[/dev/VG/]{vdev?*|zpool?*} argument(s)
# display both corresponding absolute path names from
# /dev/VG/?*
# and
# /dev/disk/by-id/dm-uuid-?*

rc=0 # Return Code / exit value, change if failure(s)
nl='
'

progname="$(basename "$0")" || progname="$0"

VGs="$(vgs -o vg_name --noheadings | Ss)"

[ -n "$VGs" ] || {
	rc=1
	printf '%s\n' "$0: no VGs found, aborting"
	exit "$rc"
}

[ "$#" -ge 1 ] || {
	rc=1
	printf '%s\n' "usage: $progname {[/dev/disk/by-id/]dm-uuid-?*|[/dev/VG/]{vdev?*|zpool?*}} ..." 2>&1
	exit "$rc"
}

for d # my device(s)
do
	case "$d" in
		dm-uuid-?*|/dev/disk/by-id/dm-uuid-?*)
			# d for original, D for absolute
			case "$d" in
				/*) D="$d";;
				*) D="/dev/disk/by-id/$d";;
			esac
			set -- $(
				ls -Lond "$D" 2>>/dev/null |
				awk '/^b/ {if(NR==1) print $4,$5};{if(NR>=2)exit;}' |
				tr -d ,;
			)
			major="$1"; minor="$2"
			set --
			{
				printf '%s\n' "$major" |
				grep '^[0-9]\{1,\}$' >>/dev/null 2>&1 &&
				printf '%s\n' "$minor" |
				grep '^[0-9]\{1,\}$' >>/dev/null 2>&1
			} || {
				rc=1
				printf '%s\n' "$progname: unable to find: $d" 1>&2
				continue
			}
			set -- $(
				for VG in $VGs
				do
					ls -Lond /dev/"$VG"/vdev?* /dev/"$VG"/zpool?* 2>>/dev/null |
					awk '/^b/ {if( $5 ~ /^'"$minor"'$/ && $4 ~ /^'"$major"',$/)print $9}'
				done
			)
			if [ "$#" -eq 1 ]; then
				printf '%s\n' "$* $D"
			else
				rc=1
				printf '%s %s\n' "$progname: unable to find" \
					"${*:+unique }match for $d${*:+:$nl$* $D}" 1>&2
			fi
		;;
		vdev?*|zpool?*|/dev/*/vdev?*|/dev/*/zpool?*)
			# d for original, D for absolute
			DD= # for our absolute match(es)
			case "$d" in
				/*)
					D="$d"
					# sanity check absolute
					set -- $(
						printf '%s\n' "$D" |
						awk -F/ \
							'
								{if(NF!=4)exit;}
								{if(NR!=1)exit;}
								{print "/" $2 "/" $3,$4}
							'
						)
					case "$2" in
						vdev?*|zpool?*)
							:
						;;
						*)
							rc=1
							printf '%s\n' "$progname: invalid name, expecting to match [/dev/disk/by-id/]dm-uuid-?*|[/dev/VG/]{vdev?*|zpool?*} but got: $d" 1>&2
							continue
						;;
					esac;
					for VG in $VGs
					do
						[ /dev/"$VG" = "$1" ] &&
						[ -e /dev/"$VG/$2" ] &&
						DD="${DD:+$DD }/dev/$VG/$2"
					done
					[ -n "$DD" ] || {
						rc=1
						printf '%s\n' "$progname: unable to find: $d" 1>&2
						continue
					}
				;;
				*)
					DD=
					for VG in $VGs
					do
						[ -e /dev/"$VG/$d" ] &&
						DD="${DD:+$DD }/dev/$VG/$d"
					done
					[ -n "$DD" ] || {
						rc=1
						printf '%s\n' "$progname: unable to find: $d" 1>&2
						continue
					}
				;;
			esac
			for D in $DD
			do
				set -- $(
					ls -Lond "$D" 2>>/dev/null |
					awk '/^b/ {if(NR==1) print $4,$5};{if(NR>=2)exit;}' |
					tr -d ,;
				)
				major="$1"; minor="$2"
				set --
				{
					printf '%s\n' "$major" |
					grep '^[0-9]\{1,\}$' >>/dev/null 2>&1 &&
					printf '%s\n' "$minor" |
					grep '^[0-9]\{1,\}$' >>/dev/null 2>&1
				} || {
					rc=1
					printf '%s\n' "$progname: unable to find: $d" 1>&2
					continue
				}
				set -- $(
					ls -Lond /dev/disk/by-id/dm-uuid-?* 2>>/dev/null |
					awk '/^b/ {if( $5 ~ /^'"$minor"'$/ && $4 ~ /^'"$major"',$/)print $9}'
				)
				if [ "$#" -eq 1 ]; then
					printf '%s\n' "$D $*"
				else
					rc=1
					printf '%s %s\n' "$progname: unable to find" \
						"${*:+unique }match for $d${*:+:$nl$D $*}" 1>&2
				fi
			done
		;;
		*)
			printf '%s\n' "$progname: invalid name, expecting to match [/dev/disk/by-id/]dm-uuid-?*|[/dev/VG/]{vdev?*|zpool?*} but got: $d" 1>&2
			rc=1
		;;
	esac
done
exit "$rc"
