#!/bin/bash
SOURCE="$0"
source /usr/lib/elive-tools/functions
EL_REPORTS="1"
#el_make_environment

# include sbin in our PATH since its needed sometimes, and there's nothing wrong by using it!
if [[ "$PATH" != *"/usr/sbin"* ]] ; then
    # needed for: partprobe, udevadm
    export PATH="${PATH}:/usr/local/sbin:/usr/sbin:/sbin"
fi


# sync wrapper to avoid syncing if wanted
sync(){
    if ((NO_SYNC)) ; then
        el_debug "ignoring sync..."
    else
        command sync
    fi
}

check_udisks_service(){
    if ((is_wheezy)) ; then
        el_dependencies_check "udisks"
    else
        el_dependencies_check "udisksctl"
    fi

    # if LC_ALL="$EL_LC_EN" udisksctl info -b "$1" 2>&1 | grep -qs "Error looking up object" ; then
    if [[ "$( LC_ALL="$EL_LC_EN" udisksctl dump 2>&1 | wc -l )" -lt 10 ]] ; then
        restart_daemons
    fi

    # if LC_ALL="$EL_LC_EN" udisksctl info -b "$1" 2>&1 | grep -qs "Error looking up object" ; then
    if [[ "$( LC_ALL="$EL_LC_EN" udisksctl dump 2>&1 | wc -l )" -lt 10 ]] ; then
        is_udisksctl_unavailable=1
    fi

}
#===  FUNCTION  ================================================================
#          NAME:  restart_daemons
#   DESCRIPTION:  Restarts udisks and polkit when we found an error trying to use the disk
#    PARAMETERS:  -
#       RETURNS:  -
#===============================================================================
restart_daemons(){
    # pre {{{
    el_debug
    el_security_function_loop 20 || return 0

    # }}}
    # restart daemons {{{
    if [[ "$UID" = 0 ]] ; then
        killall udisks-daemon 2>/dev/null || killall -9 udisks-daemon 2>/dev/null || true
        killall udisksd 2>/dev/null || killall -9 udisksd 2>/dev/null || true
        killall polkitd 2>/dev/null || killall -9 polkitd 2>/dev/null || true

        if ((is_systemd)) ; then
            systemctl restart udisks2.service polkit.service  2>/dev/null || true
        else
            { /usr/lib/udisks/udisks-daemon 2>/dev/null 1>&2 & disown ; } 2>/dev/null
            { /usr/lib/udisks2/udisksd 2>/dev/null 1>&2 & disown ; } 2>/dev/null
            { /usr/lib/policykit-1/polkitd 2>/dev/null 1>&2 & disown ; } 2>/dev/null
        fi
    else
        if el_check_sudo_automated ; then
            sudo killall udisks-daemon 2>/dev/null || sudo killall -9 udisks-daemon 2>/dev/null || true
            sudo killall udisksd 2>/dev/null || sudo killall -9 udisksd 2>/dev/null || true
            sudo killall polkitd 2>/dev/null || sudo killall -9 polkitd 2>/dev/null || true

            if ((is_systemd)) ; then
                sudo systemctl restart udisks2.service polkit.service  2>/dev/null || true
            else
                { sudo /usr/lib/udisks/udisks-daemon 2>/dev/null 1>&2 & disown ; } 2>/dev/null
                { sudo /usr/lib/udisks2/udisksd 2>/dev/null 1>&2 & disown ; } 2>/dev/null
                { sudo /usr/lib/policykit-1/polkitd 2>/dev/null 1>&2 & disown ; } 2>/dev/null
            fi
        else
            el_info "Is needed to restart some polkitd services, run again this tool from root"
        fi
    fi

    # we need to wait a bit, seems like udisks dont read anything if we don't
    sync ; sleep 2

    if LC_ALL="$EL_LC_EN" udisks_dump 2>&1 | grep -Fqs "Couldn't enumerate devices" ; then
        sleep 1
        if LC_ALL="$EL_LC_EN" udisks_dump 2>&1 | grep -Fqs "Couldn't enumerate devices" ; then
            sleep 2
            if LC_ALL="$EL_LC_EN" udisks_dump 2>&1 | grep -Fqs "Couldn't enumerate devices" ; then
                sleep 5
            fi
        fi
    fi


    # - restart daemons }}}
}
#===  FUNCTION  ================================================================
#          NAME:  refresh_partition_table
#   DESCRIPTION:  refresh disks data
#    PARAMETERS:  -
#       RETURNS:  -
#===============================================================================
refresh_partition_table(){
    # pre {{{
    local dev
    el_debug
    el_security_function_loop || return 0

    dev="$1"
    el_check_variables "dev"

    # }}}
    if [[ "$1" = /dev/nvme*p* ]] || [[ "$1" = /dev/mmcblk*p* ]] || [[ "$1" = /dev/md*p* ]] ; then
        partprobe "${dev%%p[0-9]*}" 2>/dev/null || true
    else
        partprobe "${dev%%[0-9]*}" 2>/dev/null || true
    fi
    sync ; sleep 1
}
#===  FUNCTION  ================================================================
#          NAME:  chroot_layers_mount
#   DESCRIPTION:  mount the layers needed for a working chroot
#    PARAMETERS:  $1 directory, $2 name-id-to-use, $3 = mode (opt)
#       RETURNS:  -
#===============================================================================
chroot_layers_mount(){
    # pre {{{
    local dir id mode is_mode_bind
    el_debug
    el_security_function_loop 10 || return 0

    dir="${1%%/}"
    id="$2"
    mode="$3"
    if ! el_check_variables "dir|id" || ! el_check_dirs "$dir" ; then
        exit 1
    fi

    if [[ "${UID}" != "0" ]] ; then
        el_error "must require root privileges"
    fi

    if [[ "$mode" = "bind" ]] ; then
        is_mode_bind=1
        el_debug "using bind mode of mounting layers"
    fi

    # }}}

    if check_is_mounted "${dir}/proc" 2>/dev/null 1>&2 ; then
        el_explain 3 "chroot layers already mounted"
        return 0
    fi

    # create some needed dirs if they don't exist yet:
    mkdir -p "${dir}/home" "${dir}/tmp" "${dir}/var/lib/live" "${dir}/var/lock" "${dir}/var/log" "${dir}/var/run" "${dir}/var/tmp" "${dir}/var/spool"

    # dev & devpts
    mkdir -p "$dir/dev/pts"
    if ((is_mode_bind)) ; then
        #mount --bind "/dev" "${dir}/dev"
        mount "dev-$id" -t devtmpfs "${dir}/dev" || true
        mount --bind "/dev/pts" "${dir}/dev/pts"
        mount -t tmpfs "devshm-$id" "${dir}/dev/shm"
    else
        # mount a tmpfs of type dev first, we need thigns like /dev/null working:
        mount "dev-$id" -t devtmpfs "${dir}/dev" || true

        if ((is_wheezy)) ; then
            mount "devpts-$id" -t devpts "${dir}/dev/pts" || true
        else
            mount "devpts-$id" -t devpts -o newinstance,noexec,nosuid,gid=5,mode=620 "${dir}/dev/pts" || true
        fi
    fi

    # proc
    mkdir -p "$dir/proc"
    if ((is_mode_bind)) ; then
        mount --bind "/proc" "${dir}/proc"
        rm -f "${dir}/etc/mtab"
        mkdir -p "$dir/etc"
        ln -s /proc/mounts "${dir}/etc/mtab"
    else
        mount "proc-$id" -t proc "${dir}/proc" || true
    fi

    # selinux
    if ((is_wheezy)) ; then
        if [[ -e "/selinux/enforce" ]] && [[ "$(cat /selinux/enforce)" = "1" ]] ; then
            mkdir -p "$dir/selinux"
            if ((is_mode_bind)) ; then
                mount --bind "/selinux" "${dir}/selinux"
            else
                mount "selinuxfs-$id" -t selinuxfs "${dir}/selinux" || true
            fi
        fi
    else
        if [[ -e "/sys/fs/selinux/enforce" ]] ; then
            mkdir -p "$dir/sys/fs/selinux"
            if ((is_mode_bind)) ; then
                mount --bind "/sys/fs/selinux" "${dir}/sys/fs/selinux"
            else
                mount "selinuxfs-$id" -t selinuxfs "${dir}/sys/fs/selinux" || true
            fi
        fi
    fi

    # sysfs
    mkdir -p "$dir/sys"
    if ((is_mode_bind)) ; then
        mount --bind "/sys" "${dir}/sys"
    else
        mount "sysfs-$id" -t sysfs "${dir}/sys" || true
    fi

    # efivars sysfs
    if el_check_dir_has_files "/sys/firmware/efi/" 1>/dev/null 2>&1 ; then
        mkdir -p "$dir/sys/firmware/efi/efivars"
        if ((is_mode_bind)) ; then
            mount --bind "/sys/firmware/efi/efivars" "${dir}/sys/firmware/efi/efivars"
        else
            mount "efivarfs-$id" -t efivarfs "${dir}/sys/firmware/efi/efivars" || true
        fi
    fi

    #
    if el_check_dir_has_files "/var/lib/dbus/" 1>/dev/null 2>&1 ; then
        mkdir -p "$dir/var/lib/dbus"
        if ((is_mode_bind)) ; then
            mount --bind "/var/lib/dbus" "${dir}/var/lib/dbus"
        fi
    fi

    # debian chroot mark
    mkdir -p "$dir/etc"
    if [[ -e "$dir/etc/debian_chroot" ]] ; then
        mv "$dir/etc/debian_chroot" "$dir/etc/debian_chroot.orig"
    fi
    echo "live" > "${dir}/etc/debian_chroot"

    # /run:  dbus, lvm
    if ((is_mode_bind)) ; then
        if [[ -d "/run/dbus" ]] ; then
            mkdir -p "$dir/run/dbus"
            mount --bind "/run/dbus" "${dir}/run/dbus"
            # enable access to graphical system too
            xhost local:localhost 1>/dev/null 2>&1
        fi
        if [[ -d "/run/lvm" ]] ; then
            mkdir -p "$dir/run/lvm"
            mount --bind "/run/lvm" "${dir}/run/lvm"
        fi
        if [[ -d "/run/cryptsetup" ]] ; then
            mkdir -p "$dir/run/cryptsetup"
            mount --bind "/run/cryptsetup" "${dir}/run/cryptsetup"
        fi
        if [[ -d "/run/blkid" ]] ; then
            mkdir -p "$dir/run/blkid"
            mount --bind "/run/blkid" "${dir}/run/blkid"
        fi
        if [[ -d "/run/udev" ]] ; then
            mkdir -p "$dir/run/udev"
            mount --bind "/run/udev" "${dir}/run/udev"
        fi
        if [[ -d "/run/udisks2" ]] ; then
            mkdir -p "$dir/run/udisks2"
            mount --bind "/run/udisks2" "${dir}/run/udisks2"
        fi
    fi

    # custom start-stop-daemon
    if [[ -e "$dir/sbin/start-stop-daemon" ]] ; then
        chroot "$dir" dpkg-divert --rename --quiet --add /sbin/start-stop-daemon  2>/dev/null
        echo -e "#!/bin/sh\nexit 0" > "${dir}/sbin/start-stop-daemon"
        chmod 755 "${dir}/sbin/start-stop-daemon"
    fi

    # disable dpkg syncin
    mkdir -p "$dir/etc/dpkg/dpkg.cfg.d"
    echo -e "force-unsafe-io" > "${dir}/etc/dpkg/dpkg.cfg.d/live-build"

    # flash-kernel
    if [[ -e "$dir/usr/sbin/flash-kernel" ]] ; then
        chroot "$dir" dpkg-divert --rename --quiet --add /usr/sbin/flash-kernel
        ln -fs /bin/true "${dir}/usr/sbin/flash-kernel"
    fi


    # sysv-rc
    mkdir -p "$dir/usr/sbin" 2>/dev/null
    if [[ -e "$dir/usr/sbin/policy-rc.d" ]] ; then
        chroot "$dir" dpkg-divert --rename --quiet --add /usr/sbin/policy-rc.d
        echo -e "#!/bin/sh\necho 'All runlevel operations denied by policy, made by elive modifications' >&2 \nexit 101" > "${dir}/usr/sbin/policy-rc.d"
        chmod 0755 "${dir}/usr/sbin/policy-rc.d"
    fi

    # upstart
    if [[ -e "$dir/sbin/initctl" ]] ; then
        chroot "$dir" dpkg-divert --rename --quiet --add /sbin/initctl
        echo -e "#!/bin/sh\necho 'All runlevel operations denied by policy, made by elive modifications' >&2 \nexit 101" > "${dir}/sbin/initctl"
        chmod 0755 "${dir}/sbin/initctl"
    fi

    # hosts file
    mkdir -p "$dir/etc"
    if [[ -e "$dir/etc/hosts" ]] || [[ -L "$dir/etc/hosts" ]] ; then
        mv -f "$dir/etc/hosts" "$dir/etc/hosts.orig"
    fi
    echo -e "127.0.0.1\tlocalhost localhost.localdomain\n127.0.1.1\tdebian" > "$dir/etc/hosts"
    cat /etc/hosts >> "$dir/etc/hosts"

    # resolv.conf
    mkdir -p "$dir/etc"
    if [[ -e "$dir/etc/resolv.conf" ]] || [[ -L "$dir/etc/resolv.conf" ]] ; then
        mv "$dir/etc/resolv.conf" "$dir/etc/resolv.conf.orig"
        rm -f "$dir/etc/resolv.conf"
    fi
    cp -f /etc/resolv.conf "$dir/etc/resolv.conf"

    # hostname
    mkdir -p "$dir/etc" "$dir/bin"
    if [[ -e "$dir/etc/hostname" ]] ; then
        mv "$dir/etc/hostname" "$dir/etc/hostname.orig"
    fi
    echo "localhost.localdomain" > "$dir/etc/hostname"
    if [[ -x "$dir/usr/bin/dpkg-divert" ]] ; then
        chroot "$dir" dpkg-divert --rename --quiet --add /bin/hostname  2>/dev/null
        echo -e "#!/bin/sh\necho 'localhost.localdomain'" > "$dir/bin/hostname"
        chmod 755 "$dir/bin/hostname"
    fi

    # machine-id for pulseaudio
    cp -f /etc/machine-id "$dir/etc/"

    el_explain 2 "Layers for chroot ready"

}
#===  FUNCTION  ================================================================
#          NAME:  chroot_layers_umount
#   DESCRIPTION:  umount the layers of a chroot
#    PARAMETERS:  $1 dir , $2 name-id-to-use
#       RETURNS:  -
#===============================================================================
chroot_layers_umount(){
    # pre {{{
    local dir id mode is_mode_bind
    el_debug
    el_security_function_loop 10 || return 0

    dir="${1%%/}"
    id="$2"
    mode="$3"

    if ! el_check_variables "dir|id" || ! el_check_dirs "$dir" ; then
        exit 1
    fi

    if [[ "${UID}" != "0" ]] ; then
        el_error "must require root privileges"
    fi

    if [[ "$mode" = "bind" ]] ; then
        is_mode_bind=1
        el_debug "using bind mode of umounting layers"
    fi

    # }}}

    if ! check_is_mounted "${dir}/proc" 2>/dev/null 1>&2 ; then
        el_explain 3 "chroot layers already umounted"
        return 0
    fi


    # devpts
    if ((is_mode_bind)) ; then
        if check_is_mounted "$dir/dev/shm" 2>/dev/null 1>&2 ; then
            umount "$dir/dev/shm"
        fi

        if check_is_mounted "$dir/dev/pts" 2>/dev/null 1>&2 ; then
            umount "$dir/dev/pts"
        fi

    else
        # umount /dev/pts
        if check_is_mounted "$dir/dev/pts" 2>/dev/null 1>&2 ; then
            if grep -Fqs "$dir/dev/pts" /proc/mounts || el_check_dir_has_files "$dir/"dev/pts/* ; then
                umount "$dir/dev/pts"
            else
                #umount -f "$dir/dev/pts" 2>/dev/null 1>&2 || true
                if ! umount "$dir/dev/pts" ; then
                    el_warning "unable to umount dev/pts, try with -f ?"
                fi
            fi
        fi
    fi

    # dev
    if check_is_mounted "$dir/dev" 2>/dev/null 1>&2 ; then
        for i in $(seq 10) ; do
            umount "$dir/dev" 1>/dev/null 2>&1 && break
            sleep 1
        done
        if check_is_mounted "$dir/dev" 2>/dev/null 1>&2 ; then
            el_warning "unable to umount $dir/dev"
        fi
    fi

    # proc
    if ((is_mode_bind)) ; then
        if check_is_mounted "$dir/proc" 2>/dev/null 1>&2 ; then
            umount "$dir/proc"
        fi

        # this was a link to parent /proc/mounts
        rm -f "${dir}/etc/mtab"
    else
        if check_is_mounted "$dir/proc" 2>/dev/null 1>&2 ; then
            if [[ -e "${dir}/proc/sys/fs/binfmt_misc/status" ]] ; then
                umount "$dir/proc/sys/fs/binfmt_misc"
            fi
            if [[ -e "${dir}/proc/version" ]] ; then
                umount "$dir/proc"
            fi
        fi
    fi

    # selinux
    if ((is_wheezy)) ; then
        if ((is_mode_bind)) ; then
            if check_is_mounted "$dir/selinux" 2>/dev/null 1>&2 ; then
                umount "$dir/selinux"
            fi
        else
            if check_is_mounted "$dir/selinux" 2>/dev/null 1>&2 || [[ -e "$dir/selinux/enforce" ]] ; then
                umount "$dir/selinux"
            fi
        fi
    else
        if ((is_mode_bind)) ; then
            if check_is_mounted "$dir/sys/fs/selinux" 2>/dev/null 1>&2 ; then
                umount "$dir/sys/fs/selinux"
            fi
        else
            if check_is_mounted "$dir/sys/fs/selinux" 2>/dev/null 1>&2 || [[ -e "$dir/sys/fs/selinux/enforce" ]] ; then
                umount "$dir/sys/fs/selinux"
            fi
        fi
    fi

    # efivars
    if check_is_mounted "$dir/sys/firmware/efi/efivars" 2>/dev/null 1>&2 ; then
        umount "$dir/sys/firmware/efi/efivars"
    fi

    # sysfs
    if ((is_mode_bind)) ; then
        if check_is_mounted "$dir/sys" 2>/dev/null 1>&2 ; then
            umount "$dir/sys"
        fi
    else
        if check_is_mounted "$dir/sys" 2>/dev/null 1>&2 || [[ -e "$dir/sys/class" ]] ; then
            umount "$dir/sys"
        fi
    fi

    # /var/lib/dbus for pulseaudio
    if ((is_mode_bind)) ; then
        if check_is_mounted "$dir/var/lib/dbus" 2>/dev/null 1>&2 ; then
            umount "$dir/var/lib/dbus"
        fi
    fi

    # debian chroot mark
    if [[ -e "$dir/etc/debian_chroot.orig" ]] ; then
        rm -f "${dir}/etc/debian_chroot"
        mv "$dir/etc/debian_chroot.orig" "$dir/etc/debian_chroot"
    else
        rm -f "${dir}/etc/debian_chroot"
    fi

    # dbus
    if ((is_mode_bind)) ; then
        if check_is_mounted "$dir/run/dbus" 2>/dev/null 1>&2 ; then
            umount "$dir/run/dbus"
            xhost -local:localhost 1>/dev/null 2>&1
        fi
        if check_is_mounted "$dir/run/lvm" 2>/dev/null 1>&2 ; then
            umount "$dir/run/lvm"
        fi
        if check_is_mounted "$dir/run/cryptsetup" 2>/dev/null 1>&2 ; then
            umount "$dir/run/cryptsetup"
        fi
        if check_is_mounted "$dir/run/blkid" 2>/dev/null 1>&2 ; then
            umount "$dir/run/blkid"
        fi
        if check_is_mounted "$dir/run/udev" 2>/dev/null 1>&2 ; then
            umount "$dir/run/udev"
        fi
        if check_is_mounted "$dir/run/udisks2" 2>/dev/null 1>&2 ; then
            umount "$dir/run/udisks2"
        fi
    fi

    # custom start-stop-daemon
    if [[ -e "$dir/sbin/start-stop-daemon.distrib" ]] ; then
        rm -f "${dir}/sbin/start-stop-daemon"
        chroot "$dir" dpkg-divert --rename --quiet --remove /sbin/start-stop-daemon
        mv -f "$dir/sbin/start-stop-daemon.distrib" "$dir/sbin/start-stop-daemon" 2>/dev/null || true
    fi

    # flash-kernel
    if [[ -e "$dir/usr/sbin/flash-kernel.distrib" ]] ; then
        rm -f "${dir}/usr/sbin/flash-kernel"
        chroot "$dir" dpkg-divert --rename --quiet --remove /usr/sbin/flash-kernel
        mv -f "${dir}/usr/sbin/flash-kernel.distrib" "${dir}/usr/sbin/flash-kernel" 2>/dev/null || true
    fi
    # disable dpkg syncin
    rm -f "${dir}/etc/dpkg/dpkg.cfg.d/live-build"


    # sysv-rc
    if [[ -e "$dir/usr/sbin/policy-rc.d.distrib" ]] ; then
        rm -f "${dir}/usr/sbin/policy-rc.d"
        chroot "$dir" dpkg-divert --rename --quiet --remove /usr/sbin/policy-rc.d
        mv -f "${dir}/usr/sbin/policy-rc.d.distrib" "${dir}/usr/sbin/policy-rc.d" 2>/dev/null || true
    fi

    # upstart
    if [[ -e "$dir/sbin/initctl.distrib" ]] ; then
        rm -f "${dir}/sbin/initctl"
        chroot "$dir" dpkg-divert --rename --quiet --remove /sbin/initctl
        mv -f "${dir}/sbin/initctl.distrib" "${dir}/sbin/initctl" 2>/dev/null || true
    fi

    # hosts file
    if [[ -e "$dir/etc/hosts.orig" ]] ; then
        mv -f "$dir/etc/hosts.orig" "$dir/etc/hosts"
    fi

    # resolv.conf
    if [[ -e "$dir/etc/resolv.conf.orig" ]] || [[ -L "$dir/etc/resolv.conf.orig" ]] ; then
        mv -f "$dir/etc/resolv.conf.orig" "$dir/etc/resolv.conf" 2>/dev/null || true
    fi
    if [[ -e "$dir/etc/resolv.conf.d" ]] ; then
        rm -f "$dir/etc/resolv.conf.d/original"
        rm -f "$dir/etc/resolv.conf.d/tail"
    fi

    # hostname
    rm -f "$dir/etc/hostname"
    if [[ -e "$dir/etc/hostname.orig" ]] ; then
        mv "$dir/etc/hostname.orig" "$dir/etc/hostname"
    fi
    if [[ -e "$dir/bin/hostname.distrib" ]] ; then
        rm -f "${dir}/bin/hostname"
        chroot "$dir" dpkg-divert --rename --quiet --remove /bin/hostname
        mv -f "${dir}/bin/hostname.distrib" "${dir}/bin/hostname" 2>/dev/null || true
    fi

    # machine-id for pulseaudio
    rm -f "$dir/etc/machine-id"
    # XXX note: to make pulseaudio working you must also mount as bind mode:
    # /tmp
    # ~/.pulse
    # user's $XDG_RUNTIME_DIR

    el_explain 2 "Layers for chroot umounted"

}

get_uuid(){
    local uuid dev
    dev="$1"

    for i in $( seq 4 )
    do
        uuid="$( udevadm info --query=all --name="$dev" | grep -F "ID_FS_UUID=" | sed -e 's|^.*UUID=||g' | grep "[[:alnum:]]" | sed -e '/^$/d' | tail -1 )"
        if [[ -z "$uuid" ]] ; then
            uuid="$( LC_ALL="$EL_LC_EN" udevadm info --query=all --name="$dev" | grep -F "ID_FS_UUID=" | sed -e 's|^.*UUID=||g' | grep "[[:alnum:]]" | sed -e '/^$/d' | tail -1 )"
        fi
        if [[ -z "$uuid" ]] ; then
            uuid="$( LC_ALL="$EL_LC_EN" lsblk -rino PATH,TYPE,UUID | awk -v item="${dev}" '{ if (($1 == item) && ($2 ~ /(part|crypt|lvm|disk|md|raid)/ ) ) print $3}' )"
        fi
        if [[ -z "$uuid" ]] ; then
            uuid="$( LC_ALL="$EL_LC_EN" lsblk -d -rino UUID "$dev" | head -1 )"
        fi

        if [[ -n "$uuid" ]] ; then
            echo "$uuid"
            break
        fi

        sleep 1
    done
}

#===  FUNCTION  ================================================================
#          NAME:  get_mountpoint
#   DESCRIPTION:  get the mountpoint of a device
#    PARAMETERS:  $1 = device
#       RETURNS:  -
#===============================================================================
get_mountpoint(){
    # pre {{{
    local dev mountpoint filesystem
    el_debug
    el_security_function_loop 10 || return 0

    dev="$1"
    el_check_variables "dev"
    if ((is_wheezy)) ; then
        el_dependencies_check "udisks"
    else
        el_dependencies_check "udisksctl"
    fi

    # }}}

    if [[ ! -b "$dev" ]] ; then
        el_explain 1 "$dev is not a device, skipping"
        return 1
    fi

    # redirect to the correct device if we found it easly
    if file -s "$dev" | grep -Fqs "sticky LUKS encrypted" ; then
        dev="${dev##*/}"

        if [[ -b "/dev/mapper/${dev}" ]] ; then
            dev="/dev/mapper/${dev}"
        else
            if [[ -b "/dev/mapper/${dev}_crypt" ]] ; then
                dev="/dev/mapper/${dev}_crypt"
            fi
        fi
    fi

    check_udisks_service "$dev"

    if ((is_udisksctl_unavailable)) ; then
        mountpoint="$( cat /proc/mounts | awk -v dev="$dev" '{if ($1 == dev) print $2}' | tail -1 )"
        if ! [[ -d "$mountpoint" ]] ; then
            mountpoint="$( LC_ALL="$EL_LC_EN" mount | grep -Fqs "$dev on " )"
        fi
    fi

    #mountpoint="$( udisks --show-info "$dev" | grep -F "mount paths:" | sed -e 's|^.*mount paths:||g' )"
    # we should never use LC_ALL because UTF-8 mountpoint names will break, but we need to grep for "mount paths:" so just use this option if we don't have other choice
    # update: EL_LC_EN points to en_US.UTF-8
    #if [[ -z "$mountpoint" ]] ; then
        #mountpoint="$( LC_ALL="$EL_LC_EN" udisks --show-info "$dev" | grep -F "mount paths:" | sed -e 's|^.*mount paths:||g' )"
    #fi
    if ! ((is_udisksctl_unavailable)) && [[ -z "$mountpoint" ]] ; then
        if ((is_wheezy)) ; then
            mountpoint="$( LC_ALL="$EL_LC_EN" udisks --show-info "$dev" | grep -F "mount paths:" | sed -e 's|^.*mount paths:||g' )"
        else
            mountpoint="$( LC_ALL="$EL_LC_EN" udisksctl info -b "$dev" | grep -iE "^\s+MountPoints:\s+" | sed -e 's|^.*MountPoints:\s*||g' | tail -1 )"
            # dev state test
            if [[ "$( LC_ALL="$EL_LC_EN" udisksctl info -b "$dev" | grep -iE "^\s+MountPoints:\s+" | sed -e 's|^.*MountPoints:\s*||g' | wc -l )" -gt 1 ]] ; then
                el_warning "multiple mountpoints found? from $(basename $0) and selected '$mountpoint', (udisksctl info -b '$dev' | grep -F 'MountPoints:' ):  $( udisksctl info -b "$dev" | grep -iE "^\s+MountPoints:\s+" )"
            fi
        fi

        read -r mountpoint <<< "$mountpoint"
        mountpoint="$( readlink -f "$mountpoint" )"
    fi

    # not mounted ? mount it first
    if [[ -z "$mountpoint" ]] && ! check_is_mounted "$dev" 2>/dev/null 1>&2 ; then
        #if LC_ALL="$EL_LC_EN" udisks --show-info "$dev" | grep -qs "is mounted:.*0" ; then

        #udisks --mount "$dev" 1>/dev/null
        sync
        # TODO: if i use el_mount here it fails by some strange reason, why ? get_mountpoint not gets the mountpoint correctly?
        if el_mount "$dev" 1>/dev/null ; then

            # get data again
            if ! ((is_udisksctl_unavailable)) ; then
                if ((is_wheezy)) ; then
                    mountpoint="$( LC_ALL="$EL_LC_EN" udisks --show-info "$dev" | grep -F "mount paths:" | sed -e 's|^.*mount paths:||g' )"
                else
                    mountpoint="$( LC_ALL="$EL_LC_EN" udisksctl info -b "$dev" | grep -iE "^\s+MountPoints:\s+" | sed -e 's|^.*MountPoints:\s*||g' | tail -1 )"
                    # dev state test
                    if [[ "$( LC_ALL="$EL_LC_EN" udisksctl info -b "$dev" | grep -iE "^\s+MountPoints:\s+" | sed -e 's|^.*MountPoints:\s*||g' | wc -l )" -gt 1 ]] ; then
                        el_warning "multiple mountpoints found? from $(basename $0) and selected '$mountpoint', (udisksctl info -b '$dev' | grep -F 'MountPoints:' ):  $( udisksctl info -b "$dev" | grep -iE "^\s+MountPoints:\s+" )"
                    fi
                fi

                # remove extra leading blank chars
                read -r mountpoint <<< "$mountpoint"
                mountpoint="$(readlink -f "$mountpoint" )"

                # umount it
                if [[ -n "$mountpoint" ]] ; then
                    el_umount "$mountpoint" 1>/dev/null
                fi
            fi
        fi
    fi

    # get the uuid to know if this dev is mountable (we cannot mount /dev/sda for example, or not-formatted (without uuid) partitions)
    if [[ -z "$mountpoint" ]] && ! check_is_mounted "$dev" 2>/dev/null 1>&2 ; then
        # get uuid
        uuid="$( get_uuid "$dev" )"

        if [[ -z "$uuid" ]] ; then
            #el_debug "Unable to mount $dev because has not an uuid"
            return 1
        fi

        # get FS
        #filesystem="$( udevadm info --query=all --name="$dev" | grep -F "ID_FS_TYPE=" | sed -e 's|^.*TYPE=||g' | grep "[[:alnum:]]" | sed -e '/^$/d' | tail -1 )"
        #if [[ -z "$filesystem" ]] ; then
            filesystem="$( LC_ALL="$EL_LC_EN" udevadm info --query=all --name="$dev" | grep -F "ID_FS_TYPE=" | sed -e 's|^.*TYPE=||g' | grep "[[:alnum:]]" | sed -e '/^$/d' | tail -1 )"
        #fi

        # ignore unmountable partitions:
        if echo "$filesystem" | grep -qsE "^(swap|extended|crypto_LUKS|hfs|hfsplus)$" ; then
            #el_debug "This partition is not a mountable one"
            return 1
        fi
    fi



    # get the mountpoint
    if [[ -n "$mountpoint" ]] ; then
        # disable this supposed feature, it brokes when labels of partitions includes a space like "ian home"
        #if [[ "$(echo "$mountpoint" | wc -w )" -gt 1 ]] ; then
            #el_warning "More than one mountpoint assigned to ${dev}: ${mountpoint}, using the last one"
            #mountpoint="$(echo "$mountpoint" |tr ' ' '\n' | tail -1)"
        #fi

        # and so, show the result
        echo "$mountpoint"
        return 0
    else
        # nothing get, return an error
        el_warning "unable to get mountpoint for ${dev}, is it this partition formated and mountable?"
        return 1
    fi
}
#===  FUNCTION  ================================================================
#          NAME:  check_is_mounted
#   DESCRIPTION:  returns true if a device or mountpoint is mounted
#    PARAMETERS:  $1 dev or mountpoint
#       RETURNS:  true if is mounted, false if not
#===============================================================================
check_is_mounted(){
    # pre {{{
    local arg device mountpoint is_device is_mountpoint
    el_security_function_loop 10 || return 0

    arg="$1"
    el_check_variables "arg"

    # }}}

    sync

    if [[ "$arg" = /dev/* ]] ; then
        is_device=1
        device="$arg"
        if [[ ! -b "$device" ]] ; then
            el_error "$FUNCNAME, device $device doesn't seems to exist"
            return 1
        fi
        # redirect to the correct device if we found it easly
        if file -s "$device" | grep -Fqs "sticky LUKS encrypted" ; then
            device="${device##*/}"

            if [[ -b "/dev/mapper/${device}" ]] ; then
                device="/dev/mapper/${device}"
            else
                if [[ -b "/dev/mapper/${device}_crypt" ]] ; then
                    device="/dev/mapper/${device}_crypt"
                fi
            fi
        fi
    else
        is_mountpoint=1
        mountpoint="${arg%/}"
        mountpoint="$(readlink -f "$mountpoint" 2>/dev/null )"
    fi


    if ((is_mountpoint)) ; then

        # nothing is mounted on the mountpoint if mountpoint is not a dir (or not exist at all)
        if ! [[ -d "$mountpoint" ]] ; then
            return 1
        fi

        #if LC_ALL="$EL_LC_EN" grep -qs " ${mountpoint} " /proc/mounts ; then
        # this should be a more reliable way, more regex
        if LC_ALL="$EL_LC_EN" mount | grep -Fqs " on ${mountpoint} type " ; then

            el_debug "Mountpoint $mountpoint mounted"
            echo "Mounted"
            return 0
        else
            el_debug "Mountpoint $mountpoint not mounted"
            echo "Not mounted"
            return 1
        fi
    fi


    if ((is_device)) ; then

        check_device "$device"

        if ((is_wheezy)) ; then
            # mounted
            if LC_ALL="$EL_LC_EN" udisks --show-info "$device" | grep -qs "is mounted:.*1" ; then
                el_debug "Device $device mounted"
                echo "Mounted"
                return 0
            fi
            # not mounted
            if LC_ALL="$EL_LC_EN" udisks --show-info "$device" | grep -qs "is mounted:.*0" ; then
                el_debug "Device $device not mounted"
                echo "Not mounted"
                return 1
            fi

            # nothing? return 1

            el_warning "unable to determine if $device is mounted or not, assuming is not"
            return 1
        else
            check_udisks_service "$device"

            if ! ((is_udisksctl_unavailable)) ; then
                mountpoint="$( LC_ALL="$EL_LC_EN" udisksctl info -b "$device" | grep -iE "^\s+MountPoints:\s+" | sed -e 's|^.*MountPoints:\s*||g' | tail -1 )"
                # dev state test
                if [[ "$( LC_ALL="$EL_LC_EN" udisksctl info -b "$device" | grep -iE "^\s+MountPoints:\s+" | sed -e 's|^.*MountPoints:\s*||g' | wc -l )" -gt 1 ]] ; then
                    el_warning "multiple mountpoints found? from $(basename $0) and selected '$mountpoint', (udisksctl info -b '$device' | grep -F 'MountPoints:' ):  $( udisksctl info -b "$device" | grep -iE "^\s+MountPoints:\s+" )"
                fi

                if [[ -n "$mountpoint" ]] ; then
                    echo "Mounted"
                    return 0
                else
                    echo "Not mounted"
                    return 1
                fi
            fi
        fi
    fi

    el_error "unknown mounted state for $arg"

}
#===  FUNCTION  ================================================================
#          NAME:  el_umount
#   DESCRIPTION:  overwrite layer for a real umount feature
#    PARAMETERS:  $1 dev or mountpoint that we want to umount
#       RETURNS:  true if successfull, false if not
#===============================================================================
el_umount(){
    # pre {{{
    local arg device mountpoint is_device is_mountpoint is_umounted
    el_security_function_loop 10 || return 0

    # }}}
    for arg in "$@"
    do
        sync

        unset device mountpoint is_device is_mountpoint

        if [[ ! -b "$arg" ]] && [[ ! -d "$arg" ]] && [[ ! -L "$arg" ]] && [[ ! -e "$arg" ]] ; then
            el_warning "What $arg is ? skipping.."
        fi
        if [[ "$arg" = /dev/* ]] ; then
            is_device=1
            device="$arg"
            if [[ ! -b "$device" ]] ; then
                el_error "$FUNCNAME, device $device doesn't seems to exist"
                return 1
            fi
            # redirect to the correct device if we found it easly
            if file -s "$dev" | grep -Fqs "sticky LUKS encrypted" ; then
                dev="${dev##*/}"

                if [[ -b "/dev/mapper/${dev}" ]] ; then
                    dev="/dev/mapper/${dev}"
                else
                    if [[ -b "/dev/mapper/${dev}_crypt" ]] ; then
                        dev="/dev/mapper/${dev}_crypt"
                    fi
                fi
            fi
        else
            is_mountpoint=1
            mountpoint="${arg%/}"
            mountpoint="$(readlink -f "$mountpoint" )"
        fi

        if ((is_mountpoint)) && ! check_is_mounted "$mountpoint" 2>/dev/null 1>&2 ; then
            # if we are not mounted, nothing more to do
            return 0
        fi

        if ((is_device)) ; then
            # is a wap what we try to umount ?
            if LC_ALL="$EL_LC_EN" file -s "$device" | grep -Fqs "swap file" ; then
                swapoff "$device" 2>/dev/null
                el_debug "Umounted (swap): $*"
                return 0
            fi
            # if we are not mounted, nothing more to do
            if ! check_is_mounted "$device" 2>/dev/null 1>&2 ; then
                return 0
            fi

            #otherwise get the needed data
            mountpoint="$( get_mountpoint "$device" )"

            if [[ -z "$mountpoint" ]] ; then
                el_warning "unable to get mountpoint for $device, which means that is not mounted, although this function should have not been called, everything is fine, continuing..."
                # return that is not mounted
                return 0
            fi
        fi


        ## try to umount
        #if ((is_mountpoint)) ; then
            #if [[ "$EL_DEBUG" -ge 3 ]] ; then
                #command umount "$mountpoint" || command umount "$device"
            #else
                #command umount "$mountpoint" 2>/dev/null 1>&2 || command umount "$device" 2>/dev/null 1>&2
            #fi

            #if check_is_mounted "$mountpoint" 2>/dev/null 1>&2 ; then
                #el_debug "unable to umount (umount) $dev for ${mountpoint}, trying with another alternative..."
            #else
                ## special dir created by this own tool, we don't need it anymore
                #for dir in  /mnt/*_elive
                #do
                    #if [[ -d "$dir" ]] && ! check_is_mounted "$dir" 1>/dev/null ; then
                        #rmdir "$dir"
                    #fi
                #done

                #el_debug "Umounted: $@"
                #return 0
            #fi
        #fi


        # try with gvfs-mount first, since seems like it is unable to umount with the other ones
        #if ((is_device)) ; then

        gvfs_umount "$mountpoint"

        if check_is_mounted "$mountpoint" 2>/dev/null 1>&2 ; then
            el_debug "unable to umount (gvfs-mount) $dev for ${mountpoint}, trying with udisks..."
        else
            # special dir created by this own tool, we don't need it anymore
            for dir in  /mnt/*_elive
            do
                if [[ -d "$dir" ]] && ! check_is_mounted "$dir" 1>/dev/null ; then
                    rmdir "$dir"
                fi
            done

            el_debug "Umounted: $*"
            return 0
        fi

        # try with udisks maybe
        if ((is_wheezy)) ; then
            if [[ "$EL_DEBUG" -ge 3 ]] ; then
                udisks --unmount "$mountpoint"
            else
                udisks --unmount "$mountpoint" 2>/dev/null 1>&2
            fi
        else
            # note: atm this seems like to not work
            udisksctl unmount -p "$mountpoint" --no-user-interaction # 1>/dev/null 2>&1
        fi


        if check_is_mounted "$mountpoint" 2>/dev/null 1>&2 ; then
            el_debug "unable to umount (udisks*) $dev for ${mountpoint}, trying with umount..."
        else
            # special dir created by this own tool, we don't need it anymore
            for dir in  /mnt/*_elive
            do
                if [[ -d "$dir" ]] && ! check_is_mounted "$dir" 1>/dev/null ; then
                    rmdir "$dir"
                fi
            done

            el_debug "Umounted: $*"
            return 0
        fi


        if [[ "$EL_DEBUG" -ge 3 ]] ; then
            command umount "$mountpoint" || command umount "$device" || el_sudo umount "$device"
        else
            command umount "$mountpoint" 2>/dev/null 1>&2 || command umount "$device" 2>/dev/null 1>&2 || el_sudo umount "$device" 2>/dev/null 1>&2
        fi

        if check_is_mounted "$mountpoint" 2>/dev/null 1>&2 ; then
            el_debug "unable to umount (umount) $dev for ${mountpoint}, so hum... let me think"
        else
            # special dir created by this own tool, we don't need it anymore
            for dir in  /mnt/*_elive
            do
                if [[ -d "$dir" ]] && ! check_is_mounted "$dir" 1>/dev/null ; then
                    rmdir "$dir"
                fi
            done

            el_debug "Umounted: $*"
            return 0
        fi


        # try to know why we cannot umount it
        el_processes_using_mountpoint "$mountpoint"

        # force ? we should never do this
        if ((is_forced)) ; then
            # kill all the children processes used on this mountpoint:
            el_processes_using_mountpoint "$mountpoint" kill 1>/dev/null
            el_processes_using_mountpoint "$mountpoint" kill 1>/dev/null

            gvfs_umount "$mountpoint"

            if check_is_mounted "$mountpoint" 2>/dev/null 1>&2 ; then
                el_debug "unable to umount (gvfs-mount) $dev for ${mountpoint}, trying with udisks..."
            else
                # special dir created by this own tool, we don't need it anymore
                for dir in  /mnt/*_elive
                do
                    if [[ -d "$dir" ]] && ! check_is_mounted "$dir" 1>/dev/null ; then
                        rmdir "$dir"
                    fi
                done

                el_debug "Umounted (forced): $*"
                return 0
            fi

            # try with udisks maybe
            if ((is_wheezy)) ; then
                udisks --unmount "$mountpoint" 2>/dev/null 1>&2
            else
                udisksctl unmount -f -p "$mountpoint"
            fi

            if check_is_mounted "$mountpoint" 2>/dev/null 1>&2 ; then
                el_debug "unable to umount (udisks*) $dev for ${mountpoint}, trying with umount..."
            else
                # special dir created by this own tool, we don't need it anymore
                for dir in  /mnt/*_elive
                do
                    if [[ -d "$dir" ]] && ! check_is_mounted "$dir" 1>/dev/null ; then
                        rmdir "$dir"
                    fi
                done

                el_debug "Umounted (forced): $*"
                return 0
            fi

            command umount "$mountpoint" 2>/dev/null 1>&2 || command umount "$device" 2>/dev/null 1>&2

            if check_is_mounted "$mountpoint" 2>/dev/null 1>&2 ; then
                el_warning "ok, bruteforce time"
                # supercow powers
                command umount -l "$mountpoint" || command umount -l "$device" || command umount -f "$mountpoint" || command umount -f "$device"
            else
                # special dir created by this own tool, we don't need it anymore
                for dir in  /mnt/*_elive
                do
                    if [[ -d "$dir" ]] && ! check_is_mounted "$dir" 1>/dev/null ; then
                        rmdir "$dir"
                    fi
                done

                el_debug "Umounted (forced): $*"
                return 0
            fi
        fi

        if check_is_mounted "$mountpoint" 2>/dev/null 1>&2 ; then
            el_debug "unable to umount $dev for ${mountpoint}, I'm upset now"
            return 1
        else
            el_debug "Umounted (forced): $*"
            el_warning "well, finally umounted"
            # special dir created by this own tool, we don't need it anymore
            for dir in  /mnt/*_elive
            do
                if [[ -d "$dir" ]] && ! check_is_mounted "$dir" 1>/dev/null ; then
                    rmdir "$dir"
                fi
            done

            return 0
        fi
    done
}
#===  FUNCTION  ================================================================
#          NAME:  el_mount
#   DESCRIPTION:  overwrite layer for a real mount feature
#    PARAMETERS:  $1 = device
#       RETURNS:  true if success, false if not
#===============================================================================
el_mount(){
    # pre {{{
    local dev uuid filesystem mountpoint
    el_security_function_loop 10 || return 0

    dev="$1"
    shift
    mode="$2"
    shift

    el_check_variables "dev"

    # }}}

    if [[ ! -b "$dev" ]] && [[ -n "$dev" ]] ; then
        if [[ -b "/dev/$dev" ]] ; then
            dev="/dev/$dev"
        fi
    fi

    if [[ "$dev" != "/dev/"* ]] || [[ ! -b "$dev" ]] ; then
        NOREPORTS=1 el_error "Argument passed to $FUNCNAME is not a device: $dev"
        return 1
    fi
    # redirect to the correct device if we found it easly
    if file -s "$dev" | grep -Fqs "sticky LUKS encrypted" ; then
        dev="${dev##*/}"

        if [[ -b "/dev/mapper/${dev}" ]] ; then
            dev="/dev/mapper/${dev}"
        else
            if [[ -b "/dev/mapper/${dev}_crypt" ]] ; then
                dev="/dev/mapper/${dev}_crypt"
            fi
        fi
    fi

    # pre check to know if is already mounted
    #if check_is_mounted "$dev" 2>/dev/null 1>&2 ; then
        #echo "$dev mounted in: $(get_mountpoint "$dev" )"
        #return 0
    #fi

    check_udisks_service "$dev"


    if ! ((is_udisksctl_unavailable)) ; then
        if LC_ALL="$EL_LC_EN" udisks_dump 2>&1 | grep -Fqs "Couldn't enumerate devices" ; then
            restart_daemons
        fi
    fi


    # ignore unmountable partitions:
    if LC_ALL="$EL_LC_EN" udevadm info --query=all --name="$dev" | grep -Fqs "DEVNAME=" ; then

        # get FS
        filesystem="$( udevadm info --query=all --name="$dev" | grep -F "ID_FS_TYPE=" | sed -e 's|^.*TYPE=||g' | grep "[[:alnum:]]" | sed -e '/^$/d' | tail -1 )"
        if [[ -z "$filesystem" ]] ; then
            filesystem="$( LC_ALL="$EL_LC_EN" udevadm info --query=all --name="$dev" | grep -F "ID_FS_TYPE=" | sed -e 's|^.*TYPE=||g' | grep "[[:alnum:]]" | sed -e '/^$/d' | tail -1 )"
        fi
        if echo "$filesystem" | grep -qsE "^(swap|extended|crypto_LUKS|hfs|hfsplus)$" ; then
            el_debug "Unable to mount $dev because is not a mountable partition"
            return 1
        fi

        # get uuid
        uuid="$( get_uuid "$dev" )"


        if [[ -z "$uuid" ]] ; then
            el_debug "Unable to mount $dev because has not an uuid"
            return 1
        fi

        # get type
        # UPDATE: do not enable, LVM2 devices shows as "disk" but they are mountable, so we should refer them by their uuid or fs
        # lcal devtype
        #devtype="$( LC_ALL="$EL_LC_EN" udevadm info --query=all --name="$dev" | grep -F "DEVTYPE=" | sed -e 's|^.*DEVTYPE=||g' | grep "[[:alnum:]]" | sed -e '/^$/d' | tail -1 )"
        #if [[ "$devtype" = "disk" ]] ; then
            #el_debug "Unable to mount $dev because is a disk type"
            #return 1
        #fi
    fi

    # fsck the disk in case is dirty and not mounted
    if ! ((is_udisksctl_unavailable)) ; then
        mountpoint="$( LC_ALL="$EL_LC_EN" udisksctl info -b "$dev" | grep -iE "^\s+MountPoints:\s+" | sed -e 's|^.*MountPoints:\s*||g' | tail -1 )"
        if [[ -z "$mountpoint" ]] ; then
            if tune2fs -l "$dev" 2>/dev/null | grep -iqsE "(^Filesystem state:.*errors|not clean)" ; then
                el_info "Needed filesystem reparation for '$dev', running 'fsck -yf' to it, please be patient..."
                fsck -yf "$dev"
            fi
        fi
    fi

    # check if already mounted
    if check_is_mounted "$dev" 2>/dev/null 1>&2 ; then
        echo "$dev mounted in: $(get_mountpoint "$dev" )"
        return 0
    fi

    # try to mount
    if ! ((is_udisksctl_unavailable)) ; then
        udisks_mount "$dev" "$@"
    fi

    # check if mounted
    if check_is_mounted "$dev" 2>/dev/null 1>&2 ; then
        echo "$dev mounted in: $(get_mountpoint "$dev" )"
        return 0
    fi


    # re-read partition table and try again
    refresh_partition_table "$dev"

    # try to mount
    if ! ((is_udisksctl_unavailable)) ; then
        udisks_mount "$dev" "$@"
    fi

    # check if mounted
    if check_is_mounted "$dev" 2>/dev/null 1>&2 ; then
        echo "$dev mounted in: $(get_mountpoint "$dev" ), after to re-read partition table"
        return 0
    fi

    # try again
    restart_daemons
    refresh_partition_table "$dev"

    # try to mount
    if ! ((is_udisksctl_unavailable)) ; then
        udisks_mount "$dev" "$@"
    fi

    # check if mounted
    if check_is_mounted "$dev" 2>/dev/null 1>&2 ; then
        #echo "$dev mounted in: $(get_mountpoint "$dev" ), after to: restart udev + dbus + re-read"
        echo "$dev mounted in: $(get_mountpoint "$dev" ), after to: restart udev  + re-read"
        return 0
    fi

    # ok so, maybe the filesystem is not clean so try to fix that first:
    # do not try this at home!
    #fsck -a "$dev"

    # try to mount
    if ! ((is_udisksctl_unavailable)) ; then
        udisks_mount "$dev" "$@"
    fi

    # check if mounted
    if check_is_mounted "$dev" 2>/dev/null 1>&2 ; then
        #echo "$dev mounted in: $(get_mountpoint "$dev" ), after to: restart udev + dbus + re-read"
        echo "$dev mounted in: $(get_mountpoint "$dev" ), after to: restart udev  + re-read"
        return 0
    fi


    # if root, try to mount it in any of the cases
    if [[ "$UID" = 0 ]] ; then
        refresh_partition_table "$dev"

        # get uuid
        uuid="$( get_uuid "$dev" )"

        filesystem="$( udevadm info --query=all --name="$dev" | grep -F "ID_FS_TYPE=" | sed -e 's|^.*TYPE=||g' | grep "[[:alnum:]]" | sed -e '/^$/d' | tail -1 )"
        if [[ -z "$filesystem" ]] ; then
            filesystem="$( LC_ALL="$EL_LC_EN" udevadm info --query=all --name="$dev" | grep -F "ID_FS_TYPE=" | sed -e 's|^.*TYPE=||g' | grep "[[:alnum:]]" | sed -e '/^$/d' | tail -1 )"
        fi

        # this is not reliable, we SHOULD get the uuid (it is the most reliable way to know that the FS is mountable)
        #if [[ -z "$uuid" ]] ; then
            ## second alternative, but this is buggy, it can show multiple ones and sometimes not works like test it for /dev/sda
            #if LC_ALL="$EL_LC_EN" udevadm info --query=all --name="$item" 2>&1 | grep -qs "DEVTYPE=disk" ; then
                #el_error "Unable to mount $dev because is a DISK"
                #return 1
            #fi

            ## try to get the UUID by other method
            #uuid="$( lsblk -nio UUID "$dev" | grep "[[:alnum:]]" | tail -1 )"
        #fi

        if [[ -z "$uuid" ]] ; then
            el_debug "Unable to mount $dev because has not an uuid"
            return 1
        fi

        target="/mnt/${uuid}_elive"
        mkdir -p "$target"

        if check_is_mounted "$target" 2>/dev/null 1>&2 ; then
            el_error "$target is already mounted, we cannot use it"
        fi

        mount "$dev" "$target"
        sync
        sleep 1

        # hibernated NTFS requires hack
        # check if mounted
        if [[ "$filesystem" = "ntfs" ]] && ! check_is_mounted "$dev" 2>/dev/null 1>&2  ; then
            mount -t ntfs-3g -o remove_hiberfile "$dev" "$target"
        fi

        if check_is_mounted "$dev" 2>/dev/null 1>&2 ; then
            echo "$dev mounted in: $( get_mountpoint "$dev" )"
            return 0
        else

            # try to clean FS:
            if [[ "$mode" = "recursive" ]] ; then
                return 1
            else
                if tune2fs -l "$dev" 2>/dev/null | grep -iqs "^Filesystem state:.*errors" ; then
                    el_info "Needed filesystem reparation for '$dev', running 'fsck -yf' to it, please be patient..."
                    fsck -yf "$dev"
                    $FUNCNAME "$dev" "recursive"
                    if check_is_mounted "$dev" 2>/dev/null 1>&2 ; then
                        return 0
                    else
                        el_error "Unable to mount ${dev}:\n$(file -s ${dev} ; lsblk ${dev} ; )"
                        return 1
                    fi
                fi
            fi
        fi
    else
        el_error "unable to mount $dev, try the same command from root"
    fi
}

udisks_dump(){
    if ((is_wheezy)) ; then
        udisks --dump
    else
        udisksctl dump
    fi
}

udisks_mount(){
    local dev
    dev="$1"
    shift

    if ((is_udisksctl_unavailable)) ; then
        return 1
    fi

    if ((is_wheezy)) ; then
        if [[ "$EL_DEBUG" -ge 3 ]] ; then
            timeout 60 udisks --mount "$dev" "$@"
        else
            timeout 60 udisks --mount "$dev" "$@" 1>/dev/null
        fi
    else
        if [[ "$EL_DEBUG" -ge 3 ]] ; then
            timeout 60 udisksctl mount -b "$dev" --no-user-interaction "$@"
        else
            timeout 60 udisksctl mount -b "$dev" --no-user-interaction "$@" 1>/dev/null
        fi
    fi
}

gvfs_umount(){
    local mountpoint
    mountpoint="$1"
    shift

    if ((is_wheezy)) ; then
        if [[ "$EL_DEBUG" -ge 3 ]] ; then
            gvfs-mount -u "$mountpoint"
        else
            gvfs-mount -u "$mountpoint" 2>/dev/null 1>&2
        fi
    else
        if [[ "$EL_DEBUG" -ge 3 ]] ; then
            gio mount -u "$mountpoint"
        else
            gio mount -u "$mountpoint" 2>/dev/null 1>&2
        fi
    fi
}

check_device(){
    local dev
    dev="$1"

    if ((is_udisksctl_unavailable)) ; then
        return
    fi

    if ((is_wheezy)) ; then
        if LC_ALL="$EL_LC_EN" udisks --show-info "$dev" 2>&1 | grep -Fqs "Cannot find device with major:minor" ; then
            restart_daemons
        fi
    else
        if ! udisksctl info -b "$dev" 1>/dev/null ; then
            restart_daemons
        fi
    fi
}



main(){
    # pre {{{
    local arg

    # }}}
    # Usage
    if [[ -z "${1}" ]] ; then
        echo -e "Usage: $(basename $BASH_SOURCE) options:"
        echo -e "Basic partitions / mountpoins features:"
        echo -e "--get-mountpoint dev  : get the mountpoint of a device address"
        echo -e "--check-is-mounted [dev|mountpoint]  : returns true|false if the argument is mounted"
        echo -e "--mount dev [args]  : mount a device, args must be in udisks format:"
        echo -e "                    (--mount-fstype reiserX --mount-options foo,bar)"
        echo -e "--umount [dev|mountpoint]  : umounts a device|mountpoint"
        echo -e "--umount-force [dev|mountpoint]  : umounts a device|mountpoint in a forced mode, NEVER do this unless you are a wizard in level 17"
        echo -e ""
        echo -e "Chroots related:"
        echo -e "--chroot-layers-mount directory idname  : mount the layers needed for a full-working chroot (proc, sysfs, etc)"
        echo -e "--chroot-layers-umount directory [idname] [bind]  : umount the layers"
        echo -e "                                           \ bind is a special mode that allows you to run things in the graphical system among other features"
        echo -e ""
        echo -e "Note: by checking the source code you can found shortcuts to these long commands"
        exit 1
    fi

    # checks {{{
    # wheezy uses udisks, but newer (buster?) uses udisks2 which is different
    if grep -qsE "(^7\.|wheezy)" /etc/debian_version ; then
        if [[ -x "$(which udisks)" ]] ; then
            is_wheezy=1
        fi
    else
        if ! [[ -x "$(which udisksctl)" ]] && [[ -x "$(which udisks)" ]] ; then
            is_wheezy=1
        fi
    fi

    if LC_ALL="$EL_LC_EN" udisks_dump 2>&1 | grep -Fqs "Couldn't enumerate devices" ; then
        restart_daemons
        if LC_ALL="$EL_LC_EN" udisks_dump 2>&1 | grep -Fqs "Couldn't enumerate devices" ; then
            el_array_member_add "Function 'udisks_dump' doesn't shows any valid info, perhaps a reboot may fix the problem?" "${errors_found[@]}" ; errors_found=("${_out[@]}")
        fi
    fi
    # - checks }}}

    case "$1" in
        --get-mountpoint|-g)
            shift
            get_mountpoint "$@"
            ;;
        --check-is-mounted|-c)
            shift
            if check_is_mounted "$@" ; then
                exit 0
            else
                exit 1
            fi
            ;;
        --mount|-m)
            shift
            el_mount "$@"
            ;;
        --umount|-u)
            shift
            el_umount "$@"
            ;;
        --umount-force|-uf)
            shift
            is_forced=1
            el_umount "$@"
            ;;
        --chroot-layers-mount|-clm)
            shift
            chroot_layers_mount "$@"
            ;;
        --chroot-layers-umount|-clu)
            shift
            chroot_layers_umount "$@"
            ;;
    esac

    if [[ -n "$errors_found" ]] ; then
        el_request_report_bug "${errors_found[@]}"
    fi

}

#
#  MAIN
#
main "$@"

# vim: set foldmethod=marker :
