#!/bin/sh
#
# Libmountbox provides devices list in suitable format for GTK tree
# and various dialog boxes to mount, umount, etc.
#
# (C) 2009 - SliTaz GNU/Linux project.
#

# Short usage.
usage()
{
	echo -e "\nUsage: $0 command\n
Output commands:
  list-mounted      List all mounted devices in suitable GTK tree format.
  list-umounted     List all umounted in suitable GTK tree format.
  create-file       Create an empty file with predefined size.
  add-old-crypto    Create loop-eas device.
  remove-crypto     Delete a crypto device.
  
GTKdialog boxes
  mounted-fs-infos  Display a mounted devices infos with actions.
  umounted-fs-infos Display a umounted devices infos with actions.
  remove-loop       Confirmation box.
  new-file          Parameter box for file creation.
  cryptomgr         Manage crypto device with devmapper.
  add-crypto        Pass phrase dialog.\n"
}

# Format df -h output for GTK tree.
mounted_fs_data()
{
	SIZE=`echo $RES | cut -d " " -f 2`
	USED=`echo $RES | cut -d " " -f 3`
	AVAILABLE=`echo $RES | cut -d " " -f 4`
	PCT=`echo $RES | cut -d " " -f 5`
	MOUNTED_ON=`echo $RES | cut -d " " -f 6`
}

# Update BLOCKS SIZE UUID TYPE LABEL variables
getdevinfo()
{
	local dev
	dev=${1#/dev/}
	BLOCKS=0
	if [ -f /sys/block/$dev/size ]; then
		BLOCKS=`cat /sys/block/$dev/size`
	elif [ -f /sys/block/*/$dev/size ]; then
		BLOCKS=`cat /sys/block/*/$dev/size`
	fi
	if [ $BLOCKS -gt 2097152 ]; then
		unit=G
		n=$(($BLOCKS * 10 / 2097152))
	elif [ $BLOCKS -gt 2048 ]; then
		unit=M
		n=$(($BLOCKS * 10 / 2048))
	else
		unit=K
		n=$(($BLOCKS * 5))
	fi
	SIZE=$(($n/10)).$(($n%10))$unit
	UUID=`blkid | grep ^/dev/$dev: | grep UUID= | sed 's/.*UUID=\"\([^\"]*\)\".*/\1/'`
	TYPE=`blkid | grep ^/dev/$dev: | grep TYPE= | sed 's/.*TYPE=\"\([^\"]*\)\".*/\1/'`
	LABEL=`blkid | grep ^/dev/$dev: | grep LABEL= | sed 's/.*LABEL=\"\([^\"]*\)\".*/\1/'`
}

# Generate label for device manager
dmlabel()
{
	echo crypto-$(basename $1)
}

unwrap()
{
awk '{
  if ($2 == "") last=$1;
  else {
    print last $0
    last=""
  }
}'
}

case $1 in
	list-mounted)
		# List all fs found by: df -h
		#
		for dev in `df -h | grep ^/dev/ | cut -d " " -f 1`
		do
			RO='read-only'
			mount | grep $dev | grep -q '(rw' && RO=''
			RES=`df -h $dev | unwrap | grep ^$dev`
			mounted_fs_data
			echo "$dev | $SIZE | $USED | $AVAILABLE | $PCT | $MOUNTED_ON | $RO"
		done ;;
	list-umounted)
		# List all umounted fs found by: fdisk -l
		#
		for dev in `fdisk -l | grep ^/dev | cut -d " " -f 1`
		do
			RES=`fdisk -l | grep $dev | sed s/*//g`
			START=`echo $RES | cut -d " " -f 2`
			END=`echo $RES | cut -d " " -f 3`
			BLOCKS=`echo $RES | cut -d " " -f 4`
			ID=`echo $RES | cut -d " " -f 5`
			SYSTEM=`echo $RES | cut -d " " -f 6-`
			# Bootable...
			if fdisk -l | grep $dev | grep -q "*"; then
				BOOT="yes"
			else
				BOOT="-"
			fi
			# Skip swap, extended, and mounted partitions.
			if echo $RES | grep -q "swap" || echo $RES | grep -q "Extended" ; then
				continue
			elif mount | grep -q "^$dev "; then
				continue
			else
				getdevinfo $dev
				echo "$dev | $SIZE | $SYSTEM | $TYPE | $LABEL | $BOOT | $START | $END | $BLOCKS | $ID | $UUID"
			fi
		done
		for dev in /dev/mapper/* ; do
			[ -b $dev ] || continue
			mount | grep -q "^$dev " && continue
			mdev=dm-$(ls -l $dev | awk '{ print $6 }')
			mount | grep -q "^/dev/$mdev " && continue
			getdevinfo /dev/$mdev
			echo "$dev | $SIZE | - | $TYPE | $LABEL | - | - | - | $BLOCKS | - | $UUID"
		done
		for dev in $(losetup | cut -d: -f1); do
			[ -b $dev ] || continue
			mount | grep -q "^$dev " && continue
			getdevinfo $dev
			echo "$dev | $SIZE | - | $TYPE | $LABEL | - | - | - | $BLOCKS | - | $UUID"
		done
		[ -e /dev/cdrom ] &&
		echo "/dev/cdrom | - | CD/DVD | iso9660 | - | - | - | - | - | - | -"
		for i in /sys/devices/platform/floppy.*/block:*; do 
			[ -e $i ] && echo "/dev/${i#*block:} | - | - | - | floppy | - | - | - | - | -"
		done
		;;
	mounted-fs-infos)
		# Mounted fs info and actions, rootfs or other fs.
		#
		if [ "$MOUNTED" == "/dev/root" ]; then
			export MOUNTED_DEVICE="
<window title=\"Device: rootfs\" icon-name=\"media-flash\">
<vbox>
	<text use-markup=\"true\" width-chars=\"56\">
		<label>\"
<b>/dev/root</b>
\"
		</label>
	</text>
	<text use-markup=\"true\" width-chars=\"56\">
		<input>df -h / | grep ^rootfs</input>
	</text>
	<hbox>
		<button>
			<label>Browse</label>
			<input file icon=\"folder-open\"></input>
			<action>pcmanfm / &</action>
			<action type=\"closewindow\">MOUNTED_DEVICE</action>
		</button>
		<button>
			<input file icon=\"gtk-close\"></input>
			<action type=\"closewindow\">MOUNTED_DEVICE</action>
		</button>
	</hbox>
</vbox>
</window>"
		gtkdialog --center --program=MOUNTED_DEVICE
		else
			getdevinfo $MOUNTED
			RES=`df -h $MOUNTED | grep ^$MOUNTED`
			mounted_fs_data
			export MOUNTED_DEVICE="
<window title=\"Device: $MOUNTED\" icon-name=\"media-flash\">
<vbox>
	<text use-markup=\"true\" width-chars=\"56\">
		<label>\"
Device <b>$MOUNTED</b> is mounted on <b>$MOUNTED_ON</b>

Size: $SIZE
UUID: $UUID
Type: $TYPE
Label: $LABEL
\"
		</label>
	</text>
	<hbox>
		<button>
			<label>Browse</label>
			<input file icon=\"folder-open\"></input>
			<action>pcmanfm $MOUNTED_ON &</action>
			<action type=\"closewindow\">MOUNTED_DEVICE</action>
		</button>"
if mount | grep $MOUNTED_ON | grep -q '(rw'; then
	MOUNTED_DEVICE="$MOUNTED_DEVICE
		<button>
			<label>Remount read-only</label>
			<input file icon=\"redo\"></input>
			<action>mount -o remount,ro $MOUNTED_ON</action>
			<action type=\"closewindow\">MOUNTED_DEVICE</action>
		</button>"
else
	MOUNTED_DEVICE="$MOUNTED_DEVICE
		<button>
			<label>Remount read-write</label>
			<input file icon=\"redo\"></input>
			<action>mount -o remount,rw $MOUNTED_ON</action>
			<action type=\"closewindow\">MOUNTED_DEVICE</action>
		</button>"
fi
MOUNTED_DEVICE="$MOUNTED_DEVICE
		<button>
			<label>Umount</label>
			<input file icon=\"undo\"></input>
			<action>umount $MOUNTED_ON</action>
			<action type=\"closewindow\">MOUNTED_DEVICE</action>
		</button>
		<button>
			<input file icon=\"gtk-close\"></input>
			<action type=\"closewindow\">MOUNTED_DEVICE</action>
		</button>
	</hbox>
</vbox>
</window>"
		gtkdialog --center --program=MOUNTED_DEVICE
		fi ;;
	umounted-fs-infos)
		# Mounted fs info and actions, rootfs or other fs.
		#
		case "$DEVICE" in
		/dev/mapper/*) mdev=/dev/dm-$(ls -l $DEVICE | awk '{ print $6 }');;
		*) mdev=$DEVICE;;
		esac
		getdevinfo $mdev
		export UMOUNTED_DEVICE="
<window title=\"Device: $DEVICE\" icon-name=\"media-flash\">
<vbox>
	<text use-markup=\"true\" width-chars=\"56\">
		<label>\"
Mount <b>$DEVICE</b> on <b>$MOUNT_POINT</b>

Size: $SIZE
UUID: $UUID
Type: $TYPE
Label: $LABEL
\"
		</label>
	</text>
	
	<hbox>
		<button>
			<label>Mount read-only</label>
			<input file icon=\"edit-redo\"></input>
			<action>mkdir -p $MOUNT_POINT</action>
			<action>mount -r $DEVICE $MOUNT_POINT</action>
			<action type=\"closewindow\">MOUNTED_DEVICE</action>
		</button>
		<button>
			<label>Mount read-write</label>
			<input file icon=\"edit-redo\"></input>
			<action>mkdir -p $MOUNT_POINT</action>
			<action>mount $DEVICE $MOUNT_POINT</action>
			<action type=\"closewindow\">MOUNTED_DEVICE</action>
		</button>"
while read type fsck args; do
	[ "$TYPE" == "$type" ] || continue
	which $fsck > /dev/null || continue
UMOUNTED_DEVICE="$UMOUNTED_DEVICE		
		<button>
			<label>$fsck check</label>
			<input file icon=\"drive-harddisk\"></input>
			<action>xterm -T \"$fsck $args $DEVICE\" \
				-geometry 80x12 \
				-e \"echo; $fsck $args $DEVICE; \
				echo -e '----\\nENTER to close Terminal'; \
				read i\" &</action>
			<action type=\"closewindow\">MOUNTED_DEVICE</action>
		</button>"
done <<EOT
ext3 e2fsck -p
ext2 e2fsck -p
vfat dosfsck -a
msdos dosfsck -a
xfs fsck.xfs -s
reiserfs reiserfsck --fix-fixable
jfs jfs_fsck -a
EOT
UMOUNTED_DEVICE="$UMOUNTED_DEVICE		
		<button>
			<input file icon=\"gtk-close\"></input>
			<action type=\"closewindow\">UMOUNTED_DEVICE</action>
		</button>
	</hbox>
</vbox>
</window>"
		gtkdialog --center --program=UMOUNTED_DEVICE ;;
	loopmgr)
		export LOOP_MANAGER="
<window title=\"Loop manager\" icon-name=\"media-flash\">
<vbox>
	<tree>
		<width>420</width><height>120</height>
		<variable>LOOP_DEV</variable>
		<label>Device|File|Size|Type|Label|Mounted on|Offset|UUID</label>"
		while read dev offset file; do
			DEV=$(echo $dev | cut -d: -f1)
			[ -b "$DEV" ] || continue
			MOUNT=$(mount | grep ^$DEV | awk '{ print $3 }')
			getdevinfo $DEV
			LOOP_MANAGER="$LOOP_MANAGER
		<item>$DEV | $file | $SIZE | $TYPE | $LABEL | $MOUNT | $offset | $UUID</item>
"
		done <<EOT
$(losetup)
EOT
		LOOP_MANAGER="$LOOP_MANAGER
		<action>/usr/lib/slitaz/libmountbox remove-loop</action>
		<action>/usr/lib/slitaz/libmountbox loopmgr &</action>
		<action type=\"closewindow\">LOOP_MANAGER</action>
	</tree>
	<hbox>
		<text use-markup=\"true\">
			<label>\"<b>File</b>\"</label>
		</text>
		<entry accept=\"filename\">
			<variable>FILE</variable>
		</entry>
		<button>
			<input file icon=\"folder-open\"></input>
			<action type=\"fileselect\">FILE</action>
		</button>
	</hbox>
	<hbox>
		<text use-markup=\"true\">
			<label>\"<b>Offset</b>\"</label>
		</text>
		<entry>
			<default>0</default>
			<variable>OFFSET</variable>
		</entry>
		<button>
			<label>Disable</label>
			<input file icon=\"remove\"></input>
			<action>/usr/lib/slitaz/libmountbox remove-loop</action>
			<action>/usr/lib/slitaz/libmountbox loopmgr &</action>
			<action type=\"closewindow\">LOOP_MANAGER</action>
		</button>
		<button>
			<label>Enable</label>
			<input file icon=\"add\"></input>
			<action>losetup -o \$OFFSET \$(losetup -f) \$FILE</action>
			<action>/usr/lib/slitaz/libmountbox loopmgr &</action>
			<action type=\"closewindow\">LOOP_MANAGER</action>
		</button>
		<button>
			<label>Create</label>
			<input file icon=\"filenew\"></input>
			<action>/usr/lib/slitaz/libmountbox new-file</action>
			<action>/usr/lib/slitaz/libmountbox loopmgr &</action>
			<action type=\"closewindow\">LOOP_MANAGER</action>
		</button>
		<button>
			<input file icon=\"gtk-close\"></input>
			<action type=\"closewindow\">LOOP_MANAGER</action>
		</button>
	</hbox>
</vbox>
</window>"
		gtkdialog --center --program=LOOP_MANAGER ;;
	remove-loop)
		getdevinfo $LOOP_DEV
		export REMOVE_DEVICE="
<window title=\"Device: $LOOP_DEV\" icon-name=\"media-flash\">
<vbox>
	<text use-markup=\"true\" width-chars=\"56\">
		<label>\"
Disable <b>$LOOP_DEV</b> ?

Size: $SIZE
UUID: $UUID
Type: $TYPE
Label: $LABEL
\"
		</label>
	</text>
	<hbox>
		<button yes>
			<action>umount $LOOP_DEV</action>
			<action>losetup -d $LOOP_DEV</action>
			<action type=\"closewindow\">LOOP_MANAGER</action>
			<action>/usr/lib/slitaz/libmountbox loopmgr &</action>
			<action type=\"closewindow\">REMOVE_DEVICE</action>
		</button>
		<button no>
			<action type=\"closewindow\">REMOVE_DEVICE</action>
		</button>
	</hbox>
</vbox>
</window>"
		gtkdialog --center --program=REMOVE_DEVICE ;;
	create-file)
		file=$2
		size=$3
		[ -n "$file" -a -n "$size" ] || exit
		[ "$4" == "true" ] && bs="1K"
		[ "$5" == "true" ] && bs="1M"
		[ "$6" == "true" ] && bs="1024M"
		if [ "$7" != "true" -a -e "$file" ]; then
			export FILE_EXIST="
<window title=\"File exist\" icon-name=\"media-flash\">
<vbox>
	<hbox>
		<text use-markup=\"true\">
			<label> \"The file <b>$file</b> already exists\" </label>
		</text>
	</hbox>
	<hbox>
		<button>
			<input file icon=\"gtk-close\"></input>
			<action type=\"closewindow\">FILE_EXIST</action>
		</button>
	</hbox>
</vbox>
</window>"
			gtkdialog --center --program=FILE_EXIST
			exit
		fi
		dd if=/dev/zero of=$file bs=$bs count=$size
		;;
	new-file)
		export CREATE_FILE="
<window title=\"Create file\" icon-name=\"media-flash\">
<vbox>
	<hbox>
		<text use-markup=\"true\">
			<label>\"<b>File:</b>\"</label>
		</text>
		<entry>
			<variable>FILE</variable>
$( [ -n "$FILE" ] && echo "<default>$FILE</default>" )
		</entry>
		<button>
			<input file icon=\"folder-open\"></input>
			<action type=\"fileselect\">FILE</action>
		</button>
	</hbox>
	<hbox>
		<text use-markup=\"true\">
			<label>\"<b>Size:</b>\"</label>
		</text>
		<entry>
			<variable>NEW_SIZE</variable>
			<default>0</default>
		</entry>
		<radiobutton>
			<label>Kb</label>
			<variable>KB</variable>
		</radiobutton>
		<radiobutton>
			<label>Mb</label>
			<variable>MB</variable>
		</radiobutton>
		<radiobutton>
			<label>Gb</label>
			<variable>GB</variable>
		</radiobutton>
	</hbox>
	<hbox>
		<checkbox>
			<label>Override</label>
			<variable>OVERRIDE</variable>
			<default>false</default>
		</checkbox>
		<button>
			<label>Create</label>
			<input file icon=\"filenew\"></input>
			<action>/usr/lib/slitaz/libmountbox create-file \"\$FILE\" \"\$NEW_SIZE\" \$KB \$MB \$GB \$OVERRIDE</action>
			<action type=\"closewindow\">CREATE_FILE</action>
		</button>
		<button>
			<input file icon=\"gtk-close\"></input>
			<action type=\"closewindow\">CREATE_FILE</action>
		</button>
	</hbox>
</vbox>
</window>"
		gtkdialog --center --program=CREATE_FILE ;;
	cryptomgr)
		missing=""
		for i in libdevmapper dmsetup linux-md hashalot cryptsetup ; do
			[ -d /var/lib/tazpkg/installed/$i ] || missing="$missing $i"
		done
		if [ -n "$missing" ]; then
			export CRYPTO_MANAGER="
<window title=\"Crypto manager\" icon-name=\"media-flash\">
<vbox>
	<hbox>
		<text use-markup=\"true\">
		<label>\"
<b>Need the packages :</b>

$(for i in $missing ; do echo $i; done)
\" </label>
		</text>
	</hbox>
	<hbox>
		<button>
			<label>Install</label>
			<input file icon=\"go-jump\"></input>
			<action>xterm -T \"Install packages\" \
			-geometry 80x16+120+120 -e \"for i in $missing ; do \
			yes y | tazpkg get-install \\\$i ; done; sleep 2\" \
			</action>
			<action>/usr/lib/slitaz/libmountbox cryptomgr &</action>
			<action type=\"closewindow\">CRYPTO_MANAGER</action>
		</button>
		<button>
			<input file icon=\"gtk-close\"></input>
			<action type=\"closewindow\">CRYPTO_MANAGER</action>
		</button>
	</hbox>
</vbox>
</window>"
			gtkdialog --center --program=CRYPTO_MANAGER
			exit
		fi
		for i in dm-mod dm-crypt aes-i586 ; do
			lsmod | grep -q $i || modprobe $i
		done
		export CRYPTO_MANAGER="
<window title=\"Crypto manager\" icon-name=\"media-flash\">
<vbox>
	<tree>
		<width>420</width><height>120</height>
		<variable>CRYTO_DEV</variable>
		<label>Name|Device|Size|Type|Label|Mounted on|UUID</label>"
		while read name ; do
			[ -b /dev/mapper/$name ] || continue
			DEV=/dev/dm-$(ls -l /dev/mapper/$name | awk '{ print $6 }')
			MOUNT=$(mount | egrep "^$DEV|/dev/mapper/$name" | awk '{ print $3 }')
			getdevinfo $DEV
			case "$name" in 
			*crypto*) item="item icon=\"passwd\"";;
			*)        item="item icon=\"drive-harddisk\"";;
			esac
			CRYPTO_MANAGER="$CRYPTO_MANAGER
		<$item>$name|$DEV | $SIZE | $TYPE | $LABEL | $MOUNT | $UUID</item>
"
		done <<EOT
$(ls /dev/mapper 2> /dev/null)
EOT
		CRYPTO_MANAGER="$CRYPTO_MANAGER
	</tree>
	<hbox>
		<text use-markup=\"true\">
			<label>\"<b>Device :</b>\"</label>
		</text>
		<combobox>
			<label>Device</label>
$( (losetup ; blkid | grep -v /dev/loop ) | cut -d: -f1 | awk '{ printf "<item>%s</item>\n",$1}')
			<variable>DEVICE</variable>
		</combobox>
		<text use-markup=\"true\">
			<label>\"<b>Cipher :</b>\"</label>
		</text>
		<combobox>
			<variable>CRYPTO</variable>
			<item>aes-256</item>
			<item>aes-192</item>
			<item>aes-128</item>
		</combobox>
	</hbox>
	<hbox>
		<button>
			<label>Remove</label>
			<input file icon=\"remove\"></input>
			<action>/usr/lib/slitaz/libmountbox remove-crypto</action>
			<action>/usr/lib/slitaz/libmountbox cryptomgr &</action>
			<action type=\"closewindow\">CRYPTO_MANAGER</action>
		</button>
		<button>
			<label>Create</label>
			<input file icon=\"add\"></input>
			<action>/usr/lib/slitaz/libmountbox add-crypto</action>
			<action>/usr/lib/slitaz/libmountbox cryptomgr &</action>
			<action type=\"closewindow\">CRYPTO_MANAGER</action>
		</button>
		<button>
			<label>Format</label>
			<input file icon=\"gtk-clear\"></input>
			<action>/usr/lib/slitaz/libmountbox format-crypto</action>
			<action>xterm -T \"Format LUKS\" \
			-geometry 80x16+120+120 -e \"\
			cryptsetup luksFormat -c aes -h sha\${CRYPTO#aes-} \$DEVICE \" \
			</action>
			<action>/usr/lib/slitaz/libmountbox cryptomgr &</action>
			<action type=\"closewindow\">CRYPTO_MANAGER</action>
		</button>
		<button>
			<input file icon=\"gtk-close\"></input>
			<action type=\"closewindow\">CRYPTO_MANAGER</action>
		</button>
	</hbox>
</vbox>
</window>"
		gtkdialog --center --program=CRYPTO_MANAGER ;;
	add-old-crypto)
		# Not luks format
		# Try old loop-eas
		case "$CRYPTO" in
		*128)	key="16 sha256";;
		*192)	key="24 sha384";;
		*)	key="32 sha512";;
		esac
		getdevinfo $DEVICE
		key=$(echo $PASS_PHRASE | hashalot -x -n $key)
		echo 0 $BLOCKS crypt aes-plain $key 0 $DEVICE 0 | \
				dmsetup create $(dmlabel $DEVICE)
		;;
	add-crypto)
		if cryptsetup isLuks $DEVICE 2> /dev/null; then
			xterm -T "Open LUKS" -e \
			  "cryptsetup luksOpen $DEVICE $(dmlabel $DEVICE)"
		else
			export GET_PASS_PHRASE="
<window title=\"Crypto manager\" icon-name=\"media-flash\">
<vbox>
	<hbox>
		<text use-markup=\"true\">
			<label>\"<b>Pass phrase :</b>\"</label>
		</text>
		<entry>
			<variable>PASS_PHRASE</variable>
		</entry>
		<button ok>
			<action>/usr/lib/slitaz/libmountbox add-old-crypto</action>
			<action type=\"closewindow\">GET_PASS_PHRASE</action>
		</button>
	</hbox>
</vbox>
</window>"
			gtkdialog --center --program=GET_PASS_PHRASE
		fi
		;;
	remove-crypto)
		cryptsetup luksClose $CRYTO_DEV
		[ -e /dev/mapper/$CRYTO_DEV ] && dmsetup remove $CRYTO_DEV
		;;
	*)
		usage ;;
esac

exit 0
