#!/bin/sh

if [ -r /etc/sysconfig/hotplug ] ; then
	. /etc/sysconfig/hotplug
fi

: ${HOTPLUG_DO_MOUNT:=yes}
: ${HOTPLUG_MOUNT_TYPE:=subfs}
: ${HOTPLUG_MOUNT_SYNC:=yes}
: ${USE_RAW_PARTITION:=yes}

DESKTOPDIR=/var/lib/Desktop
TEMPLATEDIR=/usr/share/hotplug/DesktopTemplates
MPDIR=/media

if [ ! -e "$DESKTOPDIR" ]; then
	mkdir /dev/shm/Desktop
	ln -snf /dev/shm/Desktop "$DESKTOPDIR"
fi

get_iocharset()
{
	# get the charmap of current system locale setting
	eval $(test -e /etc/SuSEconfig/profile &&
		. /etc/SuSEconfig/profile &&
		locale -k charmap)

	case "$charmap" in
		UTF-8)
			iocharset="utf8"
			;;
		BIG5|BIG5-HKSCS|EUC-TW)
			iocharset="cp950"
			;;
		CP1251)
			iocharset="cp1251"
			;;
		CP1255)
			iocharset="cp1255"
			;;
		EUC-JP)
			iocharset="euc-jp"
			;;
		EUC-KR)
			iocharset="cp949"
			;;
		GB18030|GBK|GB2312)
			iocharset="cp936"
			;;
		ISO-8859-*)
			iocharset="iso8859-${charmap##ISO-8859-}"
			;;
		KOI8-R)
			iocharset="koi8-r"
			;;
		KOI8-U)
			iocharset="koi8-u"
			;;
		SHIFT_JIS)
			iocharset="cp932"
			;;
		TIS-620)
			iocharset="cp874"
			;;
	esac	

	echo $iocharset
}

get_type()
{
	local device="$1"
	local type="hdd"
	local uniqueid=""
	TEMPFILE=/var/run/hotplug/hwscan_show.$$

	[ -e /sbin/hwscan ] || return

	if [ -L "$device" ]; then
		device=$(readlink -f "$device")
	fi

	for i in 0 1 2 3 4 5 6 7 8 9 ; do
		# maybe we need to wait for hwscand
		hwscan --show $device > "$TEMPFILE"
		/bin/grep -q "HW Class List:" "$TEMPFILE" && break
		sleep 1
	done

#	mesg "configuring $device"

	avail=no
	while read line ; do
                case "$line" in
			 *Unique\ ID:\ *)
				uniqueid="${line##*Unique ID: }"
				;;
			 *Config\ Status:*avail=yes*)
				avail=yes
				;;
			 *Hardware\ Class:\ *)
				type="${line##*Hardware Class: }"
				;;
			 *Features:\ *CD-R*)
				type="cdwriter"
				;;
			 *Features:\ DVD)
				type="dvd"
				;;
			 *Device:*amera*|*Model:*amera*|*Model:*dsc*|*Model:*photo*|Vendor:*FUJIFILM*)
				[ "$type" = "partition" ] && type="hdd_camera"
				[ "$type" = "disk" ] && type="hdd_camera"
				[ "$type" = "hdd" ] && type="hdd_camera"
				;;
			 *Device\ Files:*\ /dev/*/usb-*)
				[ "$type" = "partition" ] && type="hdd_usb"
				[ "$type" = "disk" ] && type="hdd_usb"
				[ "$type" = "hdd" ] && type="hdd_usb"
				;;
		esac
	done < "$TEMPFILE"
	rm -f "$TEMPFILE"

#	mesg "avail: $avail, device: $device, type: $type, uniqueid: $uniqueid"

	if [ "$avail" = "yes" ]; then
# had something todo with properly detecting cameras, maybe it's broken now
#		if [ "$type" = "hdd_usb" ]; then
#			case "${device:0-1:1}" in
#				[0123456789])
#					get_type ${device%?}
#					;;
#				*)
#					echo $type $uniqueid
#					;;
#			esac
#		else
			echo $type $uniqueid
#		fi
	fi
}

# add|remove uniqueid device mountpoint fstype flags
update_fstab()
{
	local action="$1"
	local id="$2"
	shift 2
	local device=${1:-XXX}
	local mountpoint=${2-XXX}
	mode=$(stat -c %a /etc/fstab) || { mesg "could not stat /etc/fstab"; return 1; }
	tmpfstab=$(mktemp /etc/fstab.XXXXXXXXXX) || { mesg "could not create a temporary fstab"; return 1; }
	case "$action" in
		add)
			if [ -z "$id" ]; then
				mesg "got empty uniqueid, not adding $device to fstab"
				rm -f "$tmpfstab"
				return 1
			fi
			mesg "add $device to fstab"
			# remove any stale entries
			grep -v "#HOTPLUG $id\$" < /etc/fstab >> "$tmpfstab"
			if [ -n "$*" ]; then
				echo "$@" " 0 0 #HOTPLUG $id" >> "$tmpfstab"
			fi
		;;
		remove)
			mesg "remove $device from fstab"
			# we just ignore the device here, the mountpoint matters
			grep -v "/.\\+ \\+$mountpoint .\\+#HOTPLUG .*\$" < /etc/fstab >> "$tmpfstab"
		;;
	esac
	chmod "$mode" "$tmpfstab"
	mv "$tmpfstab" /etc/fstab || rm -f "$tmpfstab"
	return 0
}

mount_media()
{
	local entry="$1"
	local device="/dev/$entry"

	[ "$2" ] && device="$2"
	# $3 is used as template selector below

	[ "${entry:0:4}" = "pci-" ] && return
	[ "${entry:0:12}" = "by-path/pci-" ] && return

	local mountpoint="$MPDIR/${entry##*/}"

	# no double mounts
	if ! awk -v dev="$device" -v mp="$mountpoint" \
		'$1 == dev || $2 == mp {exit 1}' < /proc/mounts
	then
		mesg "$device or $mountpoint already mounted"
		return
	fi

	local iocharset=$(get_iocharset)
	local iocharsetoption=""

	# iocharset option is valid for vfat, iso9660/joliet and ntfs filesystems.
	# though ntfs will use nls option instead of iocharset, we can continue to use iocharset here.
	[ -n "$iocharset" ] && iocharsetoption=",iocharset=$iocharset"

	local fstype
	local fsoptions
	local desktop
	local uniqueid

	fstype=$(/bin/guessfstype "$device" 2>/dev/null)
	fstype="${fstype##*to be:}"
	case "$fstype" in
		*null*) 
			# we should use blkid only after 9.2
			if [ ! -x /sbin/blkid ] || ! /sbin/blkid "$device" >/dev/null; then
				return 0
			fi
			;;
	esac

	eval $(set x $(get_type $device); echo desktop=$2 uniqueid=$3)

	if [ "$HOTPLUG_MOUNT_TYPE" = "subfs" ]; then
		fstype=
		fsoptions=sync,noexec$iocharsetoption # XXX why noexec?
		case $desktop in
			cdrom|cdwriter|dvd)
				fstype=fs=cdfss,
				fsoptions="ro,exec$iocharsetoption"
				;;
			floppy)
				fstype=fs=floppyfss,
				;;
			hdd_usb|hdd_camera)
				#everything is fine
				;;
			*)
				desktop=hdd
				;;
		esac
	elif [ "$HOTPLUG_MOUNT_TYPE" = "fstab" ]; then
		# not all fs support iocharset
		case "$fstype" in
			vfat|ntfs|udf|iso9660) ;;
			*) iocharsetoption="" ;;
		esac
		fstype="auto" # use auto anyway
		fsoptions="noauto,user,exec$iocharsetoption"
		[ "$HOTPLUG_MOUNT_SYNC" != "no" ] && fsoptions="$fsoptions,sync"
	else
		return 0
	fi

       	if [ "${desktop:0:3}" = "hdd" ] ; then
		case ${entry} in
		*p[0-9])
			;;
		*p[0-9][0-9])
			;;
		*)
			#skip it
			[ "$USE_RAW_PARTITION" = "yes" ] || return
			;;
		esac
       	fi

	#
	# make it possible to use an explicit file
	#
	[ "$3" ] && desktop="$3"
	
	#
	# create mountpoint and mount device
	#
	if [ ! -e "$MPDIR" ]; then
		mkdir "$MPDIR"
	fi
       	
	if [ "$HOTPLUG_MOUNT_TYPE" = "subfs" ]; then
	       	mesg "mount $entry"
	       	[ -e $mountpoint ] || mkdir $mountpoint
       		mount $device $mountpoint -t subfs \
			-o "${fstype}nodev,nosuid,procuid,$fsoptions"

		if [ "$?" = "0" ]; then
			#
			# create desktop file
			#	
			create_desktopicon "$desktop" "$device" "$mountpoint"
       		fi
	elif [ "$HOTPLUG_MOUNT_TYPE" = "fstab" ]; then
		if update_fstab add "$uniqueid" "$device" "$mountpoint" "$fstype" "$fsoptions"; then
			[ -e "$mountpoint" ] || mkdir "$mountpoint"
			[ "$HOTPLUG_DO_MOUNT" = "yes" ] && /bin/mount "$mountpoint"
			create_desktopicon "hdd_real_mount" "$device" "$mountpoint"
		fi
       	fi

	#
	# register device as configured
	#
	if [ -x /sbin/hwscanqueue ]; then
		hwscanqueue --cfg=yes $device
	fi
}

unmount_media()
{
	local entry="$1"
	local device="/dev/$entry"

	[ -n "$2" ] && device="$2"

	mountpoint="$MPDIR/${entry##*/}"

	if [ "$HOTPLUG_MOUNT_TYPE" = "subfs" ]; then
		umount $device -t subfs
		if [ "$?" = "0" ]; then
			#
			# remove desktop file
			#
			rm -f $DESKTOPDIR/${device##*/}.desktop

			rmdir "$mountpoint"
		fi
	elif [ "$HOTPLUG_MOUNT_TYPE" = "fstab" ]; then
		if grep -q "$mountpoint" /proc/mounts 2>/dev/null; then
			mesg "#### $mountpoint still mounted! ####"
		fi
		update_fstab remove "" "$device" "$mountpoint"
		[ -d "$mountpoint" ] && rmdir "$mountpoint"
		rm -f $DESKTOPDIR/${device##*/}.desktop
	else
		return
	fi
	[ -e /sbin/hwscanqueue ] && hwscanqueue --partition "$device"
}

# $1 = template name
# $2 = device
# $3 = mountpoint
create_desktopicon()
{
	local desktop="$1"
	local dev="$2"
	local mp="$3"

	[ -z "$desktop" -o -z "$dev" -o -z "$mp" ] && return

	[ ! -w "$DESKTOPDIR" -o ! -e "$TEMPLATEDIR/$desktop.desktop" ] && return

	/bin/awk -F= -v dev="$dev" -v mp="$mp" \
		'
		$1 ~ /^Name/ { $0=$0" (" dev ")" }
		{ sub(/_DEVICE_/, dev, $0); sub(/_MOUNTPOINT_/, mp, $0); print }
		' \
		< "$TEMPLATEDIR/$desktop.desktop" \
		> "$DESKTOPDIR/${device##*/}.desktop"
}

# prints:
# type device mountpoint
coldplug_read_fstab()
{
	/bin/awk < /etc/fstab \
		'
		function doprint(type) { print type, $1, $2; }
		/^#/ { next; }
		$3 ~ /subfs/ {
			doprint("subfs"); next;
		}
		# windows disks get a special icon
		$2 ~ /\/windows\// && $4 ~ /user[^_]*/ {
			doprint("hdd_windows"); next;
		}
		# any other user mountable disk
		$4 ~ /user[^_]*/ {
			doprint("hdd_real_mount"); next;
		}
		'
}

coldplug_create_subfs()
{
	coldplug_clean_subfs

	touch $DESKTOPDIR/.dummy

	coldplug_read_fstab |
	while read desktop device mountpoint; do
		if [ "$desktop" = "subfs" ]; then # figure out correct icon for subfs disk
			eval $(set x $(get_type $device)
			       echo desktop=$2)
		fi
		create_desktopicon "$desktop" "$device" "$mountpoint"
	done
	
	rm -f $DESKTOPDIR/.dummy
}

coldplug_clean_subfs()
{
#	for i in $MPDIR/*; do
#		[ -d "$i$" ] && rmdir "$i"
#	done
	:
}


# vim: syntax=sh
