
# Copyright 2015-2020 Rivoreo

# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:

# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
# FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

case "`uname -s`" in
	Linux)
		if [ -x "`which udevadm`" ]; then
			refresh_device_name_map() {
				true
			}
			get_physical_path() {
				local phys_path
				phys_path="`udevadm info --query property --name \"$1\" | grep ^ID_PATH=`" || return
				printf %s\\n "${phys_path#ID_PATH=}"
			}
		elif [ -d /dev/disk/by-path ]; then
			refresh_device_name_map() {
				local target dev
				phys_path_map=
				for f in /dev/disk/by-path/*; do
					[ -e "$f" ] || break
					[ -h "$f" ] || continue
					# Skip partitions
					[ "${f%-part*}" != "$f" ] && continue
					target="`readlink \"$f\"`" || continue
					dev="${target#../../}"
					[ "$dev" = "$target" ] && continue
					[ "${dev##*/}" != "$dev" ] && continue
					phys_path_map="phys_path=${f##*/};dev=$dev
$phys_path_map"
				done
			}
			get_physical_path() {
				local phys_path dev r=1 ORIG_IFS="$IFS"
				IFS="
"
				for entry in $phys_path_map; do
					eval "$entry"
					[ "$dev" != "$1" ] && continue
					printf %s\\n "$phys_path"
					r=0
					break
				done
				IFS="$ORIG_IFS"
				return $r
			}
		else
			# Fallback
			refresh_device_name_map() {
				true
			}
			get_physical_path() {
				printf %s\\n "$1"
			}
		fi
		;;
	*FreeBSD)
		if
			if [ -x "`which camcontrol`" ]; then
				refresh_device_name_map() {
					local cam_dev_list
					cam_dev_list="`camcontrol devlist`" || return
					phys_path_map="`printf '%s\\n' \"$cam_dev_list\" | grep -Eo ' at [ a-z0-9]+ \\([a-z]+[0-9]+(,[a-z]+[0-9]+)*\\)\$' | sed -r -e "s/ at /phys_path=/" -e 's/ \\(/;dev=/' -e "s/,?pass[0-9]+,?//" -e 's/(,[a-z0-9,]+)*\\)//' -e 's/ ([0-9])/\\1/g' -e 's/ /\\-/g'`"
				}
				refresh_device_name_map
			else
				false
			fi
		then
			get_physical_path() {
				# Skip pass(4) devices
				[ "${1#pass}" != "$1" ] && return 1
				[ -n "$phys_path_map" ] || refresh_device_name_map || return
				local phys_path dev r=1 ORIG_IFS="$IFS"
				IFS="
"
				for entry in $phys_path_map; do
					eval "$entry"
					[ "$dev" != "$1" ] && continue
					printf %s\\n "$phys_path"
					r=0
					break
				done
				IFS="$ORIG_IFS"
				return $r
			}
		else
			# Fallback
			refresh_device_name_map() {
				true
			}
			get_physical_path() {
				printf %s\\n "$1"
			}
		fi
		;;
	*)
		refresh_device_name_map() {
			true
		}
		get_physical_path() {
			printf %s\\n "$1"
		}
		;;
esac

