#!/bin/sh
# ltspfs_entry
# place in /lib/udev
# $1 = mode (add/remove)
# $2 = devicename
# $3 = fstype (optional)

ROOT=/var/run/drives
FSTAB=/var/run/ltspfs_fstab

# get default configuration:
if [ -f /etc/ltspfs/ltspfsd.conf ]; then
    . /etc/ltspfs/ltspfsd.conf
fi

# get ltsp configuration:
if [ -f /usr/share/ltsp/ltsp_config ]; then
    # Need to make sure lts.conf is rechecked if changed (eg ltsp-cluster)
    export LTSP_CONFIG=False
    . /usr/share/ltsp/ltsp_config
fi

boolean_is_true(){
    case $1 in
       # match all cases of true|y|yes
       [Tt][Rr][Uu][Ee]|[Yy]|[Yy][Ee][Ss]) return 0 ;;
       *) return 1 ;;
    esac
}

if ! boolean_is_true "$LOCALDEV" ; then
    exit 0
fi

call_ltspfsmounter()
{
    action="$1"
    MOUNTPOINT=$2
    for LDM_SOCKET in /var/run/ldm_socket_*; do
        if [ -S ${LDM_SOCKET} ]; then
            SERVER=${LDM_SOCKET##*_}
            /usr/bin/ssh -X -S ${LDM_SOCKET} ${SERVER} \
                "/usr/sbin/ltspfsmounter ${MOUNTPOINT} $action"
        fi
    done

    if [ -x "/usr/sbin/ltspfsmounter" ]; then
        # Also call local ltspfsmounter if installed
        # Don't use xauth for local mounts
        export LTSPFS_NOAUTH=True
        # always run as root, so mounts appear in /media/root
        USER=root /usr/sbin/ltspfsmounter ${MOUNTPOINT} $action

        # Add kiosk support
        unset KIOSK_FOUND
        for i in 01 02 03 04 05 06 07 08 09 10 11 12; do
            eval SCREEN=\${SCREEN_$i}
            case "$SCREEN" in 
                kiosk*) KIOSK_FOUND=True
            esac
        done
        [ -n "${KIOSK_FOUND}" ] && su - ltspkiosk -c "LTSPFS_NOAUTH=True /usr/sbin/ltspfsmounter ${MOUNTPOINT} $action"

        # if user's home directory is mounted via sshfs, assume we want a local
        # mount for localapps
        while read dev home fstype rest; do
            case "$fstype" in 
                *sshfs*)
                    export USER=${home##*/}
                    if [ -n "${USER}" ]; then
                        su ${USER} -c "LTSPFS_NOAUTH=True /usr/sbin/ltspfsmounter ${MOUNTPOINT} $action"
                    fi
                    ;;
            esac
        done </proc/mounts
    fi
}

remove_device()
{
    DEVICENAME="$1"
    unset TARGET_MOUNTPOINT
    while read DEV MOUNTPOINT TYPE OPTIONS DUMP PASS; do
        if [ "${DEV}" = "/dev/${DEVICENAME}" ]; then
            TARGET_MOUNTPOINT=$MOUNTPOINT
            break
        fi
    done < ${FSTAB}

    if [ -n "${TARGET_MOUNTPOINT}" ]; then
        # Remove the mount point in ltspfs_fstab first
        # to prevent triggering mount while umounting
        sed -i -e "\@ ${TARGET_MOUNTPOINT} @d" ${FSTAB}
        umount -l ${TARGET_MOUNTPOINT}
        rmdir ${TARGET_MOUNTPOINT}
        call_ltspfsmounter remove ${TARGET_MOUNTPOINT}
        unset TARGET_MOUNTPOINT
        exit 0
    fi
}

start_ltspfsd()
{
    if [ ! -e /var/run/ltspfsd.pid ] && [ -z "$(pgrep ltspfsd)" ]; then
        # Make this sessions secret auth cookie for ltspfs
        if [ ! -f /var/run/ltspfs_token ]; then
            mcookie > /var/run/ltspfs_token
        fi

        if [ -d /run/systemd/system ] && [ -x /bin/systemctl ]; then
            # attempt to start ltspfsd the systemd way.
            systemctl start ltspfsd
        else
            # start up the ltspfsd daemon
            /usr/bin/ltspfsd
        fi
        echo $! >/var/run/ltspfsd.pid
    fi
}

verify_device() {
    DEVICENAME="$1"
    if [ -z "$ID_TYPE" ]; then
        # set an ID type for known devices
        case $DEVICENAME in
            fd?) # internal floppy drives don't set any information
                ID_TYPE=floppy ;;
        esac
    fi

    # set devices to be denied based on simple booleans:
    if boolean_is_true "$LOCALDEV_DENY_FLOPPY" ; then
        LOCALDEV_DENY="ID_TYPE:floppy,$LOCALDEV_DENY"
    fi

    if boolean_is_true "$LOCALDEV_DENY_USB" ; then
        LOCALDEV_DENY="ID_BUS:usb,$LOCALDEV_DENY"
    fi

    if boolean_is_true "$LOCALDEV_DENY_CD" ; then
        LOCALDEV_DENY="ID_TYPE:cd,$LOCALDEV_DENY"
    fi

    # default to not allowing internal disks, as it gives write access to root
    # filesystems:
    test -z "$LOCALDEV_DENY_INTERNAL_DISKS" && LOCALDEV_DENY_INTERNAL_DISKS=True
    if boolean_is_true "$LOCALDEV_DENY_INTERNAL_DISKS" ; then
        # IDE, SCSI (which should catch sata)
        LOCALDEV_DENY="ID_BUS:ata+ID_TYPE:disk,ID_BUS:scsi+ID_TYPE:disk,$LOCALDEV_DENY"
    fi

    # Deny mounting by sysfs attribute from udevadm info (in environment)
    # LOCALDEV_DENY is a comma-separated list of var=val pairs
    if [ -n "${LOCALDEV_DENY}" ]; then
        oldifs=$IFS
        IFS=,
        for deny_ruleset in ${LOCALDEV_DENY}; do
            count=0
            IFS=+
            for deny_rule in $deny_ruleset; do
                var=$(echo $deny_rule|cut -d: -f1)
                val=$(echo $deny_rule|cut -d: -f2)
                eval test="\${$var}" 2>/dev/null
                # If $test (the value of the udevadm info var) equals $val
                # (the value from LOCALDEV_DENY), then increment count of
                # matches
                if [ "$test" = "$val" ]; then
                    count=$(($count+1))
                else
                    count=0
                    break
                fi
            done
            [ $count -gt 0 ] && exit 1
        done
        unset IFS
        if [ -n "$oldifs" ]; then
            IFS=$oldifs
        fi
    fi

    # Make sure we have a valid FSTYPE
    [ -z "${FSTYPE}" ] && FSTYPE="${ID_FS_TYPE}"   # Use udevadm info ID_FS_TYPE
    [ "${FSTYPE}" = "swap" ] && exit 1             # Don't mount swap partitions
    [ -z "${FSTYPE}" ] && exit 1  # That's empty too, die.
}

add_device() {
    DEVICENAME="$1"
    for link in $(udevadm info -q symlink -n ${DEVICENAME}) ; do
        case $link in
            cdrom*) 
                LABEL="$link"
                break
                ;;
        esac
    done

    case $DEVICENAME in
        fd*) 
            LABEL="floppy${DEVICENAME##fd}"
            ;;
        cdrom*)
            LABEL="${DEVICENAME}"
            ;;
    esac

    [ -z "${LABEL}" ] && LABEL=${ID_FS_LABEL}
    [ -z "${LABEL}" ] && LABEL="${ID_BUS}${ID_TYPE}-${DEVICENAME}"

    # Check for existing label with same name
    if [ -r ${FSTAB} ]; then
        while read DEV MOUNTPOINT TYPE OPTIONS DUMP PASS; do
            if [ "${DEV##*/}" = "$DEVICENAME" ]; then
                # Duplicate entry, don't bother to re-add.
		exit 0
            elif [ "${MOUNTPOINT##*/}" = "${LABEL}" ]; then
                # Seems we already have a mountpoint with this name
                # Let's change the label
                LABEL="${LABEL}-${DEVICENAME}"
            fi
        done < ${FSTAB}
    fi
 
    # Invent $MOUNTPOINT
    MOUNTPOINT=$ROOT/$LABEL
    mkdir -p ${MOUNTPOINT}

    # Set "utf8" option if volume is vfat, iso9660, or ntfs (which support it)
    # This fixes filenames with international characters
    case ${FSTYPE} in
        vfat|iso9660|ntfs) LOCALDEV_MOUNT_OPTIONS=${LOCALDEV_MOUNT_OPTIONS:-"defaults,utf8"} ;;
    esac     

    echo "/dev/${DEVICENAME} ${MOUNTPOINT} ${FSTYPE} ${LOCALDEV_MOUNT_OPTIONS:-defaults} 0 0" >> ${FSTAB}

    call_ltspfsmounter add ${MOUNTPOINT}
}

case "$1" in
    add|remove|add_disc|remove_disc) 
        MODE=$1
        shift
        ;;
    *)  
        # backwards compatibility:
        # called as add_fstab_entry or remove_fstab_entry
        # Get basename of $0
        MODE=${0##*/} 
        ;;
esac

# Get basename of $1
DEVICENAME=${1##*/}
FSTYPE=$2

eval "export $(udevadm info -qenv -n ${DEVICENAME}|sed -e 's/=/="/' -e 's/$/"/')"

case $MODE in
    add*) 
        verify_device $DEVICENAME
        start_ltspfsd
        add_device $DEVICENAME 
        ;;
    remove*) 
        remove_device $DEVICENAME 
        ;;
    *) exit 1 ;;
esac
