#!/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_LOCK=$UDEV_DRIVE_ICON_ROOT/.lock
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=""
	if [ $SHOW_VOLUME_LABEL -a "$1" -a "$1" != "unknown" ]; then
		[ "$1" != "crypto_LUKS" ] && BLKID='busybox blkid' || BLKID='blkid'	# BB blkid doesn't recognize LUKS2 labels
		SUMMARY=$($BLKID $DEVNAME | sed -n "\_^${DEVNAME}:.* LABEL=_ {"'s/.* LABEL="\([^"]*\)".*/\1/; p}')
	fi
	#[ $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 $(awk -vp=$p 'BEGIN {printf("%.1f",p/1024)}')GiB" || SUMMARY="$SUMMARY ${p}MiB" # convert to GiB (=1024 MiB) if more than 2GiB
	[ "$1" ] && SUMMARY="$SUMMARY $1"

	# handle single quotes
	VOLABEL=$(echo "$VOLABEL" | sed s_\'_'&\\&&'_g)
	SUMMARY=$(echo "$SUMMARY" | sed s_\'_'&\\&&'_g)
}


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

### add handler - get devices information
udev_add_handler() {
	PROCEED=
	FS_TYPE=$(guess_fstype $DEVNAME)
	
	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 ;;
		*)	# 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'
FS_TYPE='$FS_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
mkdir -p $UDEV_DRIVE_ICON_ROOT

### run the rest under lock - one at a time
{ flock -x 9 # start flock

# init drive icon
if [ ! -e $UDEV_DRIVE_ICON_EVENTS ]; then
	mkdir -p $UDEV_DRIVE_ICON_EVENTS $UDEV_DRIVE_ICON_DEVICES
	echo -1 > $UDEV_EVENT_COUNTER
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

} 9>$F_LOCK # end flock

