#!/bin/dash
# get information needed for creating drive icons
# (C) James Budiono 2012, 2013, 2015
# License: GNU GPL Version 3 or later
#
# Version 1 - Support multiple X desktops
# Version 2 - re-written to back-end/front-end to make it easier to port to another desktop
#             (front-end is fatdog-drive-icon-start-v2.sh)
#           - multiple X desktop supports is now handled by front-end automatically
# Version 3 - re-write - now only responsible to drive info. Icons are fully managed by front-end.
#
# called from udev where ACTION=add/remove/change and SUBSYSTEM=block, executed as root, no X
# uses uses ACTION, DEVNAME, DEVPATH environments

### system configuration - no need to change
export PATH=/usr/bin:/usr/sbin:/bin:/sbin:/lib64/udev:/lib/udev:/libexec
UDEV_DRIVE_ICON_ROOT=/tmp/udev-fatdog-drive-icon
UDEV_DRIVE_ICON_EVENTS=$UDEV_DRIVE_ICON_ROOT/events
UDEV_DRIVE_ICON_DEVICES=$UDEV_DRIVE_ICON_ROOT/devices
UDEV_EVENT_COUNTER=$UDEV_DRIVE_ICON_ROOT/counter
COUNTER_MAX=100  # max number of queued events

F_MUTEX=$UDEV_DRIVE_ICON_ROOT/busy
MUTEX_TIMEOUT=200 # 20 seconds (unit is 1/10 seconds)

DEBUG_FILE=$UDEV_DRIVE_ICON_ROOT/log
DEBUG=

### run-time variables
DRIVENAME=${DEVNAME##*/}
SHOW_VOLUME_LABEL=yes
EVENTMANAGER_CONFIG=/etc/eventmanager

#################### utilities #####################
# output $@ to debug file
log_debug() {
	[ "$DEBUG" ] && echo "$@" >> $DEBUG_FILE
}

### simple, stupid, but quick way to determine drive type 
# $1-drivename $2-devpath returns DRIVE_TYPE ("primary-secondary")
guess_drive_type() {
	DRIVE_TYPE=any
	case $1 in 
		fd*) DRIVE_TYPE=floppy ;;
		sr*) DRIVE_TYPE=optical ;;
		mmc*) DRIVE_TYPE=card ;;
	esac
	case $2 in
		*usb*) DRIVE_TYPE="$DRIVE_TYPE-usb"
	esac
}

### get summary for mouseover tip window display
# $DEVNAME, $1-FS_TYPE returns SUMMARY, VOLABEL
get_summary() {
	SUMMARY=""
	[ $SHOW_VOLUME_LABEL -a "$1" -a "$1" != "unknown" ] && SUMMARY=$(busybox blkid $DEVNAME | sed -n "\_^${DEVNAME}:_ {"'/LABEL/ {s/.*LABEL="\([^"]*\)".*/\1/; p}}')
	#[ $SHOW_VOLUME_LABEL ] && SUMMARY=$(disktype $DEVNAME | sed -n '/Volume name/ { s/.*\(".*"\).*/\1/; p}')
	VOLABEL="$SUMMARY"
	read p < /sys/$DEVPATH/size
	p=$(( p / 2048 )) # convert to MiB (= 1024 KB) assuming 512-byte units
	[ $p -ge 2048 ] && SUMMARY="$SUMMARY $(( p / 1024))GiB" || SUMMARY="$SUMMARY ${p}MiB" # convert to GiB (=1024 MiB) if more than 2GiB
	[ "$1" ] && SUMMARY="$SUMMARY $1"
}


#################### mutex management #####################

# get mutex
get_mutex() {
	local timeout=$MUTEX_TIMEOUT
	while ! mkdir $F_MUTEX; do
		sleep 0.1; 
		case $timeout in 
			0) break ;;
			*) timeout=$((timeout - 1)) ;;
		esac
	done
	log_debug lock $DRIVENAME
}

# release mutex
release_mutex() {
	rmdir $F_MUTEX
	log_debug unlock $DRIVENAME
}


#################### main udev handlers here #####################

### add handler - get devices information
udev_add_handler() {
	PROCEED= FS_TYPE=""
	
	guess_drive_type $DRIVENAME $DEVPATH 	# returns DRIVE_TYPE
	case $DRIVE_TYPE in
		floppy*) PROCEED=yes ;; # floppy - always display
		optical*) cdrom_id $DEVNAME | grep -q "ID_CDROM_MEDIA.*=1" && # optical - check if there is disc inside
				  PROCEED=yes && cdrom_id --lock-media $DEVNAME ;; #fatdog-drive-icon-poll-optical.sh $DEVNAME ;;
		*)	FS_TYPE=$(guess_fstype $DEVNAME) # others - show icon if we recognise the filesystem
			case "$FS_TYPE" in 	  				
				unknown|""|Usage*|swap) log_debug "$DEVNAME filesystem unknown" ;; # unknown or swap - do nothing
				*) PROCEED=yes;;
			esac ;;
	esac

	if [ $PROCEED ]; then
		get_summary $FS_TYPE # returns SUMMARY	
		cat > $UDEV_DRIVE_ICON_DEVICES/$DRIVENAME << EOF
DRIVENAME='$DRIVENAME'
DEVNAME='$DEVNAME'
DRIVE_TYPE='$DRIVE_TYPE'
SUMMARY='$SUMMARY'
VOLABEL='$VOLABEL'
EOF
	fi
}

### remove and change handler - directly implemented, see below

#################### main #####################
#DEVPATH=/devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
#DEVNAME=/dev/sr0

case $DRIVENAME in loop*) exit ;; esac	# ignore these devices

[ -e $EVENTMANAGER_CONFIG ] && . $EVENTMANAGER_CONFIG # SHOW_VOLUME_LABEL
if [ ! -e $UDEV_DRIVE_ICON_ROOT ]; then
	# init drive icon
	mkdir -p $UDEV_DRIVE_ICON_ROOT
	get_mutex
	mkdir -p $UDEV_DRIVE_ICON_EVENTS
	mkdir -p $UDEV_DRIVE_ICON_DEVICES
	echo -1 > $UDEV_EVENT_COUNTER
else
	get_mutex
fi

# check for disc eject request
if [ $DISK_EJECT_REQUEST ]; then
	grep -q "^$DEVNAME " /proc/mounts && umount $DEVNAME # un-mount if mounted
	! grep -q "^$DEVNAME " /proc/mounts && cdrom_id --eject-media $DEVNAME	
fi

# get info for devices
case $ACTION in
	add)	udev_add_handler ;;
	remove)	rm $UDEV_DRIVE_ICON_DEVICES/$DRIVENAME ;;
	change) rm $UDEV_DRIVE_ICON_DEVICES/$DRIVENAME; udev_add_handler ;;
esac

# record the event
read counter < $UDEV_EVENT_COUNTER
counter=$(( $counter + 1 ))
[ $counter -gt $COUNTER_MAX ] && counter=0

log_debug notify $counter $ACTION $DRIVENAME
echo $ACTION $DRIVENAME > $UDEV_DRIVE_ICON_EVENTS/$counter
echo $counter > $UDEV_EVENT_COUNTER

release_mutex
