#!/bin/ksh
#
# ident "@(#)utprepmount.ksh	1.16	05/05/24 SMI"
#
# Copyright 2004-2005 Sun Microsystems, Inc.  All Rights Reserved.
# Use is subject to license terms.
#
# utprepmount:
# This script is used by the Sun Ray mounter utility
# It is not meant for general use
#

PATH="/bin:/usr/bin:/usr/sbin"

IDCMD="/usr/xpg4/bin/id"

# list of filesystem types to try fstyp
FST_LIST="ufs pcfs hsfs udfs"

# list of filesystem types to try mount
FSM_LIST="pcfs ufs hsfs udfs"

# Number of Solaris slices
SNUMPART=16
FNUMPART=5

# Sun Ray paths
SUNWUTPATH=""
SUNWUTSESSIONS=""
SUNWUTSESSUNIT="unit"

# Sun Ray utilities
UTDOMOUNTCMD=""

# command line args
ARG_MOUNT=""
ARG_UMOUNT=""
ARG_BLKDEV=""
ARG_UID=""
ARG_XID=""
ARG_SLICE=""
ARG_FSTYPE=""

# program name
PROGNAME=""

# find mount path
# $1 = block device path
#
function getmountpoint
{
	TMPMOUNTPOINT="`mount | nawk '($3 == NBLOCKDEV) { print $1 }' NBLOCKDEV=$1`"
	if [[ -z $TMPMOUNTPOINT ]] then
		# look for pcfs suffixes
		for PSUFFIX in :c :d :e :f
		do
			TMPMOUNTPOINT="`mount | nawk '($3 == NBLOCKDEV) { print $1 }' NBLOCKDEV=$1$PSUFFIX`"
			if [[ -n $TMPMOUNTPOINT ]] then
				break
			fi
		done
	fi

	print $TMPMOUNTPOINT
}


# find device mounted on this directory
# $1 = mount point
#
function getmountdev
{
	# should be valid directory name
	if [[ -d $1 ]] then
		mount | nawk '($1 == NMNTPATH) { print $3 }' NMNTPATH=$1
	fi
}


# mount block device node
#
function do_mount
{
	USER_ID=$ARG_UID
	BLKDEVPATH=$ARG_BLKDEV
	DISPLAY_ID=$ARG_XID
	SLICENUM=$ARG_SLICE

	if [[ -z $USER_ID ]] then
		print -u2 "$PROGNAME: Invalid user id"
		return 1
	fi

	if [[ -z $DISPLAY_ID ]] then
		print -u2 "$PROGNAME: Invalid display id"
		return 1
	fi

	# is this a valid block device
	if [[ ! -b $BLKDEVPATH ]] then
		print -u2 "$PROGNAME: Invalid device name $BLKDEVPATH"
		return 1
	fi

	# see whether already mounted (shouldn't be)
	MNTPT="`getmountpoint $BLKDEVPATH`"

	if [[ -z $MNTPT ]] then
		# check with session path
		UNITDEVSUFFIX="`echo $BLKDEVPATH \
					| sed -n 's:^.*/\(dev/dsk/.*\):\1:p'`"
		# /tmp/SUNWut/sessions/4/unit/dev/dsk/disk1s4
		BLKSESSPATH=$SUNWUTSESSIONS/$DISPLAY_ID/$SUNWUTSESSUNIT/$UNITDEVSUFFIX
		if [[ -b $BLKSESSPATH ]] then
			MNTPT="`getmountpoint $BLKSESSPATH`"
		fi
	fi

	if [[ -n $MNTPT ]] then
		print -u2 "$PROGNAME: $BLKDEVPATH already mounted at $MNTPT"
		return 1
	fi

	RAWDEVLINK="`echo $BLKDEVPATH \
			| sed -n 's:/dev/dsk/:/dev/rdsk/:p'`"

	# is this a valid raw device
	if [[ ! -c $RAWDEVLINK ]] then
		print -u2 "$PROGNAME: Invalid device name $BLKDEVPATH"
		return 1
	fi

	# if utprepmount has been invoked using -F option then just try
	# to mount using that filesystem type

	if [[ -n $ARG_FSTYPE ]] then
		$UTDOMOUNTCMD -m -f $ARG_FSTYPE -b $BLKDEVPATH -i $USER_ID -l
		return $?
	fi

	# if utprepmount has not been invoked using -F option then try
	# looking for a filesystem from our list
	STATUS=0
	for FS in $FST_LIST
	do
		FSTYPE="`/usr/lib/fs/$FS/fstyp $RAWDEVLINK`"
		STATUS=$?
		if [[ ( $STATUS -eq 0 ) && ( -n $FSTYPE ) ]] then
			# run mount command
			$UTDOMOUNTCMD -m -f $FSTYPE -b $BLKDEVPATH \
							-i $USER_ID -l
			STATUS=$?
			if [[ $STATUS -eq 0 ]] then
				break
			fi
		fi
	done

	if [[ ( $STATUS -ne 0 ) ]] then
		# try to mount a filesystem from our list
		for FS in $FSM_LIST
		do
			# run mount command
			$UTDOMOUNTCMD -m -f $FS -b $BLKDEVPATH -i $USER_ID -l
			STATUS=$?
			if [[ $STATUS -eq 0 ]] then
				break
			fi
		done
	fi

	return $STATUS
}


# unmount filesystem from given block device node
# note that mount point could exist even though block device does not exist
# This script is called when the device is unplugged & links removed
#
function do_umount
{
	USER_ID=$ARG_UID
	BLKDEVPATH=$ARG_BLKDEV
	DISPLAY_ID=$ARG_XID

	if [[ -z $USER_ID ]] then
		print -u2 "$PROGNAME: Invalid user id"
		return 1
	fi

	if [[ -z $DISPLAY_ID ]] then
		print -u2 "$PROGNAME: Invalid display id"
		return 1
	fi

	# strip path prefix to get base name
	DEVBASENAME=${BLKDEVPATH##*/}

	ISA=`uname -p`

	if [[ -z $ISA ]] then
		print -u2 "$PROGNAME: Unknown isa"
		return 1
	fi

	# get device alias by removing partition suffix
	if [[ "X$ISA" = "Xi386" ]] then
		DEVALIAS=${DEVBASENAME%p[0-9]}
	elif [[ "X$ISA" = "Xsparc" ]] then
		DEVALIAS=${DEVBASENAME%s[0-9]}
	else
		print -u2 "$PROGNAME: Unknown isa"
		return 1
	fi

	# remove name suffix to get path
	DEVROOT=${BLKDEVPATH%/*}

	if [[ -z $DEVALIAS || -z $DEVROOT ]] then
		print -u2 "$PROGNAME: Invalid device name $BLKDEVPATH"
		return 1
	fi

	# unmount all slices
	pnum=0
	while (( pnum < $SNUMPART ))
	do
		PARTNAME=${DEVROOT}/${DEVALIAS}"s"${pnum}
		MNTPT="`getmountpoint $PARTNAME`"

		if [[ -z $MNTPT ]] then
			# check with session path
			UNITDEVSUFFIX="`echo $PARTNAME \
					| sed -n 's:^.*/\(dev/dsk/.*\):\1:p'`"
			# /tmp/SUNWut/sessions/4/unit/dev/dsk/disk1s4
			BLKSESSPATH=$SUNWUTSESSIONS/$DISPLAY_ID/$SUNWUTSESSUNIT/$UNITDEVSUFFIX
			MNTPT="`getmountpoint $BLKSESSPATH`"
		fi
		if [[ -n $MNTPT ]] then
			# run umount command
			$UTDOMOUNTCMD -u -p $MNTPT -i $USER_ID
		fi
		(( pnum=pnum + 1 ))
	done

	# unmount all fdisk partitions
	pnum=0
	while (( pnum < $FNUMPART ))
	do
		PARTNAME=${DEVROOT}/${DEVALIAS}"p"${pnum}
		MNTPT="`getmountpoint $PARTNAME`"

		if [[ -z $MNTPT ]] then
			# check with session path
			UNITDEVSUFFIX="`echo $PARTNAME \
					| sed -n 's:^.*/\(dev/dsk/.*\):\1:p'`"
			# /tmp/SUNWut/sessions/4/unit/dev/dsk/disk1s4
			BLKSESSPATH=$SUNWUTSESSIONS/$DISPLAY_ID/$SUNWUTSESSUNIT/$UNITDEVSUFFIX
			MNTPT="`getmountpoint $BLKSESSPATH`"
		fi
		if [[ -n $MNTPT ]] then
			# run umount command
			$UTDOMOUNTCMD -u -p $MNTPT -i $USER_ID
		fi
		(( pnum=pnum + 1 ))
	done
	return 0
}


# print usage message on stderr
# $n = error message (optional)
#
function showusage
{
	MESSAGE="$*"
	if [[ -n $MESSAGE ]] then
		print -u2 "ERROR: $MESSAGE"
	fi
	print -u2 "usage:"
	print -u2 "\t $PROGNAME -m -i uid -b block_device -d display_id [-s slice] [-F fstype] "
	print -u2 "\t $PROGNAME -u -i uid -b block_device -d display_id"

	exit 1
}


# main
#

# strip path prefix to get program name
PROGNAME=${0##*/}

# need super user privileges (setuid not allowed)
if [[ "`$IDCMD -u -r`" != "0" ]] then
	print -u2 "$PROGNAME: permission denied"
	exit 1
fi

# setup Sun Ray paths
UTDOMOUNTCMD="/etc/opt/SUNWut/basedir/lib/utdomount"
SUNWUTPATH="/tmp/SUNWut"
SUNWUTSESSIONS=$SUNWUTPATH"/sessions"

# parse options
#
while getopts :b:d:i:ms:uF: vopts
do
	case $vopts in
		b) ARG_BLKDEV=$OPTARG
			;;
		d) ARG_XID=$OPTARG
			;;
		i) ARG_UID=$OPTARG
			;;
		m) ARG_MOUNT="1"
			;;
		s) ARG_SLICE=$OPTARG
			;;
		u) ARG_UMOUNT="1"
			;;
		F) ARG_FSTYPE=$OPTARG
			;;
		\?) showusage "Invalid option -$OPTARG"
			;;
		:) showusage "Required argument missing"
			;;
	esac
done

# check mutually exclusive operations
if [[ ( -n $ARG_MOUNT ) && ( -n $ARG_UMOUNT ) ]] then
	showusage "bad args: $*"
fi

# carry out operation
if [[ -n $ARG_MOUNT ]] then
	do_mount
else
	if [[ -n $ARG_UMOUNT ]] then
		do_umount
	else
		showusage "-m or -u option required"
	fi
fi

exit $?
