#!/bin/bash
SOURCE="$0"
source /usr/lib/elive-tools/functions
source /usr/lib/elive-tools/functions_hdtools
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: udevadm
    export PATH="${PATH}:/usr/local/sbin:/usr/sbin:/sbin"
fi



get_all_partitions_list(){
    # get a normal list of partitions {{{
    # note: if we use like nvme[0-9]* AND extra partitioning... we don't need that, since the first already includes them (short version), so dont saturate this with extra loops
    #for i in /dev/mapper/* /dev/[shv]d[a-z][0-9]* /dev/xvd[a-z][0-9]* /dev/vd[a-z] /dev/[shv]d[a-z] /dev/nvme[0-9]*n /dev/nvme[0-9]*n[0-9]* /dev/mmcblk[0-9]* /dev/mmcblk[0-9]*[0-9]*
    for i in \
        /dev/mapper/* \
        /dev/[shv]d[a-z][0-9]* \
        /dev/xvd[a-z][0-9]* \
        /dev/[shv]d[a-z] \
        /dev/nvme[0-9]*n* \
        /dev/nvme[0-9]*p* \
        /dev/mmcblk[0-9]*p* \
        /dev/md[0-9][0-9][0-9]*p* \
        /dev/nbd[0-9]*p*
    do
        if [[ -b "$i" ]] ; then
            if udevadm info --query=name --name="$i" 2>/dev/null 1>&2 ; then
                el_array_member_add "${i}" "${partitions_raw_arr[@]}" ; partitions_raw_arr=("${_out[@]}")
            else
                el_warning "Found device $i but doesn't seems to be reachable by udevadm, maybe is a vanished partition, skipping..."
            fi
        fi
    done
    # debug:
    el_debug "Partitions get in traditional mode as from /dev/[sh]d[a-z][0-9]*: ${partitions_raw_arr[*]}"

    # }}}
    # LVM support {{{
    if [[ -x /sbin/pvdisplay ]] && [[ -x /sbin/vgchange ]] && ( /sbin/vgchange -ay 2>/dev/null | grep -q "logical volume.*active" ) ; then
        # loop between the partitions that are used for a LVM (physical volume)
        for pvname in $( LC_ALL="$EL_LC_EN" /sbin/pvdisplay 2>/dev/null | grep -F "PV Name" | sed 's|^.*/dev/|/dev/|g')
        do
            # remove extra leading blank chars
            read -r pvname <<< "$pvname"
            [[ ! -b "${pvname}" ]] && continue
            # remove partition from our list if is part of a group
            el_array_member_unset "${pvname}" "${partitions_raw_arr[@]}" ; partitions_raw_arr=("${_out[@]}")
            el_debug "Removed ${pvname} from our list of partitions because it is part of a Physical Volume (LVM2) set"
        done

        # any logical volume (real partition inside lvm2 setup) to add?
        #for lvname in $( LC_ALL="$EL_LC_EN" lvdisplay 2>/dev/null | grep -F "LV Path" | sort -u | sed 's|^.*LV Path||g' )
        #do
            ## remove extra leading blank chars
            #read -r lvname <<< "$lvname"
            #[[ ! -b "${lvname}" ]] && continue
            #el_array_member_add "${lvname}" "${partitions_lvm2_lv_arr[@]}" ; partitions_lvm2_lv_arr=("${_out[@]}")
            #el_debug "Adding (LVM2) ${lvname} Logical Volume to our partitions list"
        #done

        # this one seems to be more standard:
        # note: this is the way os-prober does it, but seems like linux mint 17 is configured when installed like the previous mode, actually im looking a migration-mode of the installer that is unable to boot on that setup so let's try to use back the old mode ^
        # note2: i think that the problem was that cryptab file was not configured/set at all, let's put it back

        while read -ru 3 lvname
        do
            # remove extra leading blank chars
            read -r lvname <<< "$lvname"
            [[ ! -b "${lvname}" ]] && continue
            el_array_member_add "${lvname}" "${partitions_lvm2_lv_arr[@]}" ; partitions_lvm2_lv_arr=("${_out[@]}")
            el_debug "Adding (LVM2) ${lvname} Logical Volume to our partitions list"
        done 3<<< "$( LVM_SUPPRESS_FD_WARNINGS=1 lvs --noheadings --separator : -o vg_name,lv_name 2>/dev/null | sed "s|-|--|g;s|^[[:space:]]*\(.*\):\(.*\)$|/dev/mapper/\1-\2|" )"
        unset lvname pvname
    fi

    # }}}
    # RAID support (software) {{{
    if [[ -x /sbin/mdadm ]] && ( cat /proc/mdstat | grep -q " : active.*raid" ) ; then
        for raid in $(cat /proc/mdstat | grep " : active.*raid" | sed -e 's|: active.*$||g' )
        do
            # remove extra leading blank chars
            read -r raid <<< "$raid"

            # remove elements that composes raids
            #for dev in $( cat /proc/mdstat | grep "^${raid} :" | tr ' ' '\n' | grep "\[[[:digit:]]\]" | sed 's|\[.*$||g' )
            for dev in $( LC_ALL="$EL_LC_EN" mdadm --detail "/dev/${raid}"  | grep "active sync.*/dev/" | sed -e 's|^.*/dev/|/dev/|g' )
            do
                [[ ! -b "${dev}" ]] && continue
                el_array_member_unset "${dev}" "${partitions_raw_arr[@]}" ; partitions_raw_arr=("${_out[@]}")
                el_debug "Removed ${dev} from our list of partitions because it is part of a (software) RAID set [unit]"
                unset dev
            done

            # remove the raid item too
            [[ ! -b "/dev/${raid}" ]] && continue
            el_array_member_unset "/dev/${raid}" "${partitions_raw_arr[@]}" ; partitions_raw_arr=("${_out[@]}")
            el_debug "Removed /dev/${raid} from our list of partitions because it is part of a (software) RAID set [set]"

            # scan the raid set for get names
            raidname="$( mdadm --detail "/dev/${raid}" | grep -E "\s+Name : " | sed -e 's|\s*Name : ||g' | head -1 )"

            for part in /dev/md/${raidname}p*
            do
                [[ ! -b "${part}" ]] && continue
                el_array_member_add "${part}" "${partitions_soft_raid_arr[@]}" ; partitions_soft_raid_arr=("${_out[@]}")
                el_debug "Adding (soft-RAID) $part to our partitions list"
            done


        done
        unset dev raid
    fi

    # }}}
    # RAID support (fake-raid - bios featured)) {{{
    if [[ -x /sbin/dmraid ]] && [[ -d /dev/mapper ]] ; then

        bios_raid_list="$( LC_ALL="$EL_LC_EN" /sbin/dmraid -r 2>/dev/null | grep -vE "^(no raid disks|no block devices found)$" | sed 's|\",.*$||g' | sed 's|:\ .*\"| |g')"

        if [[ -n "$bios_raid_list" ]] ; then
            echo "$bios_raid_list" > "/tmp/.bios_raid_list-$USER"

            while read -r bios_raid_disk
            do
                # RESULTS:
                # /dev/sdb jmicron_GRAID
                # /dev/sda jmicron_GRAID
                for bios_raid_partition in "$bios_raid_disk"
                do
                    [[ -z "$bios_raid_partition" ]] && continue

                    bios_raid_partition_id="$( echo "$bios_raid_partition" | awk '{print $2}' )"
                    [[ -z "$bios_raid_partition_id" ]] && continue

                    for bios_raid_partition_real in /dev/mapper/${bios_raid_partition_id}*
                    do
                        [[ -z "$bios_raid_partition_real" ]] && continue

                        if [[ -b "${bios_raid_partition_real}" ]] ; then
                            unset mounted
                            bios_raid_partition_remove="$( echo "$bios_raid_partition" | awk '{print $1}' )"
                            bios_raid_partition_add="${bios_raid_partition_real}"
                            for bios_raid_partition_remove_number in ${bios_raid_partition_remove}*
                            do
                                [[ "$bios_raid_partition_remove_number" = "${bios_raid_partition_remove}" ]] && continue
                                [[ ! -b ${bios_raid_partition_remove_number} ]] && continue

                                if [[ ! "$mounted" = "yes" ]] ; then
                                    mkdir -p "/tmp/.mount_tests_$$"
                                    if mount "$bios_raid_partition_add" "/tmp/.mount_tests_$$" 2>/dev/null ; then
                                        mounted=yes
                                        umount "/tmp/.mount_tests_$$" 2>/dev/null
                                    fi
                                    rmdir "/tmp/.mount_tests_$$"
                                fi
                                if [[ "$mounted" = "yes" ]] ; then
                                    listpartitions="$( echo ${listpartitions} | sed "s|${bios_raid_partition_remove_number}||g" )"
                                else
                                    break
                                fi
                            done

                            [[ ! "$mounted" = "yes" ]] && break
                            listpartitions="$( echo ${listpartitions} | sed "s|${bios_raid_partition_remove}||g" )"

                            if ! echo -e "${listpartitions}" | grep -Fqs "${bios_raid_partition_add}" ; then
                                listpartitions="${listpartitions} ${bios_raid_partition_add}"
                            fi
                        fi
                    done
                    unset bios_raid_partition_remove bios_raid_partition_add
                done
                unset bios_raid_partition
            done < "/tmp/.bios_raid_list-$USER"

            rm -f "/tmp/.bios_raid_list-$USER"


            listpartitions="$( echo ${listpartitions} | sed "s|/dev/mapper/${bios_raid_partition_id} ||g" )"
            unset bios_raid_list bios_raid_partition_id

        fi
    fi

    # put the original list on our array list
    for item in ${listpartitions}
    do
        [[ -b "$item" ]] && el_array_member_add "${item}" "${partitions_fake_raid[@]}" ; partitions_fake_raid=("${_out[@]}")
    done


    # }}}
    # lsblk listing {{{
    for item in $( lsblk -rino PATH )
    do
        [[ "$item" = "/dev/loop"* ]] && continue
        [[ -b "$item" ]] && el_array_member_add "${item}" "${partitions_all_lsblk[@]}" ; partitions_all_lsblk=("${_out[@]}")
    done

    # - lsblk listing }}}
}

main(){
    # pre {{{
    local bios_raid_disk bios_raid_list bios_raid_partition_add bios_raid_partition_id bios_raid_partition_remove item_dm_name item_filesystem item_human_label item_human_size item_is_usable item_label item_size item_type item_uuid line listpartitions partition raidname partitions partitions_fake_raid partitions_soft_raid_arr partitions_lvm2_lv_arr partitions_raw_arr arg
    #local bios_raid_disk bios_raid_list bios_raid_partition_add bios_raid_partition_id bios_raid_partition_remove item_dm_name item_filesystem item_human_label item_human_size item_is_usable item_label item_size item_type item_uuid line

    # ways to get partitions:
    # lsblk -f
    # /proc/partitions
    # sfdisk | fdisk
    # fdisk -l /dev/[sh]d?

    # more info (size, fs, etc)
    # parted /dev/sda print

    # show uuid|label:
    # blkid
    # udevadm info --query=all --name=/dev/mapper/vg_rootdisk-lv_var

    if ! el_dependencies_check "udevadm" ; then
        if ! el_dependencies_install udev ; then
            exit 1
        fi
    fi

    if grep -qsE "(^7\.|wheezy)" /etc/debian_version ; then
        is_wheezy=1
        sfdisk_print_id="--print-id"
    else
        if grep -qsE "(^10\.|buster)" /etc/debian_version ; then
            sfdisk_print_id="--part-id"
        else
            sfdisk_print_id="--part-type"
        fi
    fi

    # }}}

    for arg in "$@"
    do
        case "$arg" in
            --show-all)
                is_show_all=1
                shift
                ;;
            --show-all-raw)
                is_show_all=1
                is_show_raw=1
                shift
                ;;
            --show-raw)
                is_show_raw=1
                shift
                ;;
            --show-disks)
                is_show_disks=1
                shift
                ;;
            --show-all-mountable)
                is_show_all=1
                is_show_only_mountable=1
                get_all_partitions_list
                shift
                ;;
            #--show-all-umountable)
                #is_show_all=1
                #is_show_only_umountable=1
                #get_all_partitions_list
                #shift
                #;;
            --show-only-mountable|--only-mountable)
                # to be used with --show-only
                is_show_only_mountable=1
                shift
                ;;
            #--show-only-umountable)
                #is_show_only_umountable=1
                #shift
                #;;
            --show-only=*)
                el_array_member_add "${arg#--show-only=}" "${partitions_raw_arr[@]}" ; partitions_raw_arr=("${_out[@]}")
                shift
                ;;
            *)
                echo -e "Usage: $(basename $0) [option]" 1>&2
                echo -e "--show-all" 1>&2
                echo -e "--show-raw  shows also 'layers' partitions like encrypted or extended" 1>&2
                echo -e "--show-disks  shows also the 'disks', not only partitions" 1>&2
                echo -e "--show-all-mountable" 1>&2
                #echo -e "--show-all-umountable" 1>&2
                echo -e "--show-only=/dev/partition - to obtain data from a partition" 1>&2
                echo -e "\nStructure and Fields:" 1>&2
                echo -e "1         2       3             4        5              6       7             8" 1>&2
                echo -e "device :: type :: filesystem :: label :: human_label :: size :: human_size :: uuid\n" 1>&2
                shift
                ;;
        esac
    done

    if ((is_show_all)) ; then
        get_all_partitions_list
    fi

    # get extra data for each partition {{{
    for item in "${partitions_raw_arr[@]}" "${partitions_lvm2_lv_arr[@]}" "${partitions_soft_raid_arr[@]}" "${partitions_fake_raid[@]}" "${partitions_all_lsblk[@]}"
    do
        if [[ -b "$item" ]] ; then
            if [[ "$EL_DEBUG" -gt 2 ]] ; then
                if ! el_array_member_check "$item" "${partitions_raw_arr[@]}" && ! el_array_member_check "$item" "${partitions_lvm2_lv_arr[@]}" && ! el_array_member_check "$item" "${partitions_soft_raid_arr[@]}" && ! el_array_member_check "$item" "${partitions_fake_raid[@]}" ; then
                    el_warning "dev '$item' was not detected in the normal listing but only from lsblk"
                fi
            fi
            el_array_member_add "${item}" "${partitions_all_arr[@]}" ; partitions_all_arr=("${_out[@]}")
        fi
    done

    el_debug "items: \"${partitions_all_arr[*]}\""
    for item in "${partitions_all_arr[@]}"
        #for item in "${partitions_raw_arr[@]}"
    do
        [[ ! -b "$item" ]] && continue
        # debug
        #echo -e "D: $item"

        while read -ru 3 line
        do
            # udevadm needs to be restarted?
            if [[ "$line" = "device node not found" ]] ; then
                el_request_report_bug "udevadm was unable to show '$item - $(file -s "$item")', why?"
                #el_warning "Device $item is not reachable, partition was deleted?"
                #continue
            fi
            # normal partitions
            if [[ "${line}" = *"ID_FS_USAGE=filesystem" ]] ; then
                item_is_usable=1
                item_type="filesystem"
            fi
            if [[ "${line}" = *"DEVTYPE=partition" ]] ; then
                item_is_usable=1
            fi
            if [[ "${line}" = *"DEVTYPE=disk" ]] ; then
                ## betatest with Ventoy EFI partition while running in Live mode
                if [[ -n "$( LC_ALL="$EL_LC_EN" lsblk -rino PATH,TYPE,FSTYPE | awk -v item="${item}" '{ if (($1 == item) && ($2 ~ /(part|crypt|lvm)/ ) ) print $1}' )" ]] ; then
                    item_filesystem="$( get_filesystem "$item" )"
                    if [[ -n "$item_filesystem" ]] ; then
                        item_is_usable=1
                        item_type="filesystem"
                    fi
                else
                    item_filesystem="disk"
                    item_human_label="(entire disk)"
                    if ((is_show_disks)) ; then
                        item_is_usable=1
                    fi
                fi
            fi
            # swap partitions
            if [[ "${line}" = *"ID_FS_TYPE=swap" ]] ; then
                item_is_usable=1
                item_type="swap"
                item_filesystem="swap"
                item_human_label="(swap)"
            fi
            # special partitions
            if [[ "${line}" = *"ID_FS_TYPE=crypto_"* ]] ; then
                # an encrypted partition is like an extended partition which requires a password, which contains other partitions inside, it should be not considered a real partition and its dangerous to have it selectable, so ignore it:
                # but we need it to show up for the installer (unlocking encrypted ones)
                if ((is_show_raw)) ; then
                    item_is_usable=1
                else
                    item_is_usable=0
                fi
            fi

            # get label
            if [[ "${line}" = *"ID_FS_LABEL="* ]] ; then
                item_label="$(echo "$line" | sed -e 's|^.*ID_FS_LABEL=||g' )"
                item_human_label="$item_label"
            fi
            # get FS
            if [[ "${line}" = *"ID_FS_TYPE="* ]] ; then
                item_filesystem="$(echo "$line" | sed -e 's|^.*ID_FS_TYPE=||g' )"
            fi
            # get UUID
            if [[ "${line}" = *"ID_FS_UUID="* ]] ; then
                item_uuid="$(echo "$line" | sed -e 's|^.*ID_FS_UUID=||g' )"
                if ! [[ -b "/dev/disk/by-uuid/$item_uuid" ]] ; then
                    el_debug "detected uuid ${item_uuid} for ${item} but it doesn't exist in /dev, removing uuid from list"
                    unset item_uuid

                    # full debug:
                    # UPDATE: not-formated partitions has not uuid (so they needs to be considered real partitions if we want to select them as available, but they are not possible to be mounted)
                    #if [[ "$EL_DEBUG" -gt 2 ]] ; then
                        #el_debug "$(basename $0) checking '${item}', it is not a partition? (no UUID):"
                        #LC_ALL="$EL_LC_EN" udevadm info --query=all --name="$item" 1>&2
                    #fi
                fi
            fi

            # get sizes
            if [[ "${line}" = *"UDISKS_PARTITION_SIZE="* ]] ; then
                item_size="$(echo "$line" | sed -e 's|^.*UDISKS_PARTITION_SIZE=||g' | sort -ug | tail -1 )"

                if [[ -n "$item_size" ]] ; then
                    item_human_size="$(echo "scale=3; ${item_size%/*} / 1024 / 1024 / 1024" | bc -l )"

                    if [[ -n "$item_human_size" ]] && [[ "$item_human_size" != 0 ]] ; then
                        if [[ "$item_human_size" = .* ]] ; then
                            # if starts with a dot, represented in GB, its like:  .120 (so 120 MB, not gb)
                            item_human_size="${item_human_size#.} MB"
                        else
                            # else it has more than 1GB, so lets remove the last 2 numbers and show it like: 250.3 GB
                            item_human_size="${item_human_size:0:-2} GB"
                        fi
                    fi

                    item_human_size="${item_human_size#0}"
                    item_human_size="${item_human_size#0}"
                fi
            fi


            # raid (soft) ones
            if [[ "${line}" = *"MD_LEVEL=raid"* ]] ; then
                item_type="$(echo "$line" | sed -e 's|^.*MD_LEVEL=||g' )"
            fi
            if [[ "${line}" = *"MD_NAME="* ]] ; then
                item_label="$(echo "$line" | sed -e 's|^.*MD_NAME=||g' )"
                item_human_label="(${item_type}) ${item_label}"
            fi

            # LVM2 ones:
            if [[ "${line}" = *"DM_LV_NAME="* ]] ; then
                item_label="$(echo "$line" | sed -e 's|^.*DM_LV_NAME=||g' )"
                # if it has a name, even if not formatted show it so we can select it
                item_is_usable=1
            fi
            # vg_name comes after vl_name in the output
            if [[ "${line}" = *"DM_NAME="* ]] ; then
                item_dm_name="$(echo "$line" | sed -e 's|^.*DM_NAME=||g' )"
                # now we have item_vg_name var
                item_human_label="(LVM2) ${item_dm_name}"
            fi


            # END checks
            if ((is_show_only_mountable)) ; then
                # suspended device?
                if [[ "${line}" = *"DM_SUSPENDED=1" ]] ; then

                    if ((is_show_raw)) ; then
                        item_is_usable=1
                    else
                        item_is_usable=0
                    fi
                    el_warning "seems like the device $item is in suspension, make it running if you want to use it"
                fi
                # UPDATE: some lvm2 devices shows as disk but they are usable and mountable, so do not enable this option, we should reffer to these items by their fs or uuid
                #if [[ "${line}" = *"DEVTYPE=disk"* ]] ; then
                    #item_is_usable=0
                    #el_debug "ignoring partition ${item} because is considered a disk"
                #fi
            fi

        done 3<<< "$( LC_ALL="$EL_LC_EN" udevadm info --query=all --name="$item" 2>&1 )"


        # re- fixes
        if [[ -z "$item_size" ]] ; then
            item_size="$( LC_ALL="$EL_LC_EN" lsblk -b -rino PATH,TYPE,SIZE | awk -v item="${item}" '{ if (($1 == item) && ($2 ~ /(part|crypt|lvm|disk|md|raid)/ ) ) print $3}' | sort -ug | tail -1 )"
            if [[ -n "$item_size" ]] ; then
                item_human_size="$(echo "scale=3; ${item_size%/*} / 1024 / 1024 / 1024" | bc -l )"

                if [[ -n "$item_human_size" ]] && [[ "$item_human_size" != 0 ]] ; then
                    if [[ "$item_human_size" = .* ]] ; then
                        # if starts with a dot, represented in GB, its like:  .120 (so 120 MB, not gb)
                        item_human_size="${item_human_size#.} MB"
                    else
                        # else it has more than 1GB, so lets remove the last 2 numbers and show it like: 250.3 GB
                        item_human_size="${item_human_size:0:-2} GB"
                    fi
                fi

                item_human_size="${item_human_size#0}"
                item_human_size="${item_human_size#0}"

                # set a default value to not break the output
                [[ -z "$item_human_size" ]] && item_human_size="unknown"
            fi
        fi

        if [[ -n "$item_filesystem" ]] ; then
            if [[ "$item_filesystem" = "vfat" ]] ; then
                item_hd="$( get_disk_from_partition_complex "$item" )"
                if LC_ALL=C fdisk -l "${item_hd}" 2>/dev/null | grep -qs "^${1}.*EFI " ; then
                    item_human_label="EFI"
                fi
            fi
        else
            item_filesystem="$(get_filesystem "$item" )"
            if [[ -n "$item_filesystem" ]] ; then
                item_is_usable=1

                if [[ "${item_filesystem}" = "BIOS" ]] ; then
                    item_human_label="(BIOS boot)"
                fi
                if [[ "${item_filesystem}" = "EFI" ]] ; then
                    item_human_label="(EFI)"
                fi
                if [[ "${item_filesystem}" = "swap" ]] ; then
                    item_type="swap"
                    item_filesystem="swap"
                    item_human_label="(swap)"
                fi
            fi
        fi
        # do not use next one, since not everytime item_type is empty, we should just search fro crypt*
        #if [[ -z "$item_type" ]] && [[ "$item_filesystem" = crypt* ]] ; then
        #item_type="locked"
        #fi
        if [[ -z "$item_type" ]] && [[ -z "$item_uuid" ]] && [[ -z "$item_label" ]] && [[ -z "$item_filesystem" ]] ; then
            item_human_label="(unformatted)"
        fi

        # entire disks
        if [[ "$item_filesystem" = "disk" ]] ; then
            unset item_filesystem
            item_type="disk"

            if ((is_show_disks)) ; then
                item_is_usable=1
            else
                el_debug "marking ${item} as unusable because is shows like a disk"
                item_is_usable=0
            fi
        fi

        # extended partitions
        if [[ "$item_filesystem" = "extended" ]] ; then
            unset item_filesystem
            item_type="extended"
            item_human_label="(extended partition layer)"

            if ((is_show_raw)) ; then
                item_is_usable=1
            else
                el_debug "marking ${item} as unusable because is shows like an extended partition"
                item_is_usable=0
            fi
        fi

        if [[ -z "$item_human_label" ]] ; then
            item_human_label="(no name)"
        fi

        # only show mountable partitions ? {{{
        if ((is_show_only_mountable)) ; then
            # if no uuid is because the partiton is not formated
            if [[ -z "$item_uuid" ]] ; then
                item_is_usable=0
            fi
            # if not FS from a first time, mark it to not show
            if [[ -z "$item_filesystem" ]] ; then
                item_is_usable=0
            fi
            # common not mountable partitions
            if echo "$item_filesystem" | grep -qsiE "^(swap|extended|crypto_LUKS)$" ; then

                if ((is_show_raw)) ; then
                    item_is_usable=1
                else
                    item_is_usable=0
                fi
            fi
            # never consider macosx partitions mountable in our tools, the are useless for us
            if echo "$item_filesystem" | grep -qsiE "^(hfs|hfsplus)$" ; then
                item_is_usable=0
            fi
            # reiser 4
            if echo "$item_filesystem" | grep -Fqs "reiser4" ; then
                if ! grep -Fqs "reiser4" /proc/filesystems ; then
                    modprobe reiser4 2>/dev/null
                    if ! grep -Fqs "reiser4" /proc/filesystems ; then
                        item_is_usable=0
                    fi
                fi
            fi
            # btrfs
            if echo "$item_filesystem" | grep -Fqs "btrfs" ; then
                #if ! grep -qs "btrfs" /proc/filesystems ; then
                #modprobe btrfs 2>/dev/null

                if ! grep -Fqs "btrfs" /proc/filesystems ; then
                    item_is_usable=0
                fi
                #fi
            fi
        fi

        # }}}

        # add it to our list
        if ((item_is_usable)) ; then
            el_array_member_add "${item}::${item_type}::${item_filesystem}::${item_label}::${item_human_label}::${item_size}::${item_human_size}::${item_uuid}" "${partitions[@]}" ; partitions=("${_out[@]}")
        else
            if echo "$item" | grep -qs "[[:digit:]]$" ; then
                el_debug "$item is not considered a mountable or usable partition, not including it in the list"
            fi
        fi

        # next loop
        unset item item_is_usable item_type item_filesystem item_label item_human_label item_size item_vg_name item_dm_name item_human_size item_uuid
    done
    # - get extra data for each partition }}}

    # Results

    # XXX: note: these are special cases:
    # filesystem: LVM2_member : its a (real) partition but meant to be used for a lvm
    # filesystem: crypto_LUKS : its a (real) encrypted partition, must be mounted first

    for item in "${partitions[@]}"
    do
        [[ -z "${item}" ]] && continue
        #echo -e "$item"

        if ! printf "%s\n" "$item" ; then
            el_warning "problem echoing with printf item: $item"
        fi
        ##echo -en "\t" ; file -Ls "$item"
    done

}

get_filesystem(){
    local fs dev
    dev="$1"
    # make sure that we get the filesystem

    # use hal
    #fs="$(get_filesystem_hal "$dev" )"
    #if [[ -n "$fs" ]] ; then
        #echo "$fs"
        #return 0
    #fi

    # lsblk
    fs="$(get_filesystem_lsblk "$dev" )"
    read -r fs <<< "$fs"
    if [[ -n "$fs" ]] ; then
        el_debug "FS found for '$dev' as '$fs' in mode lsblk"
        echo "$fs"
        return 0
    fi

    # use "file"
    fs="$(get_filesystem_file "$dev" )"
    read -r fs <<< "$fs"
    if [[ -n "$fs" ]] ; then
        el_debug "FS found for '$dev' as '$fs' in mode file"
        echo "$fs"
        return 0
    fi

    # use "sfdisk"
    fs="$(get_filesystem_sfdisk "$dev" )"
    read -r fs <<< "$fs"
    if [[ -n "$fs" ]] ; then
        el_debug "FS found for '$dev' as '$fs' in mode sfdisk"
        echo "$fs"
        return 0
    fi

    # we have not get it?
    return 1
}
get_filesystem_lsblk(){
    local fs item
    item="$1"

    fs="$( LC_ALL="$EL_LC_EN" lsblk -rino PATH,TYPE,FSTYPE | awk -v item="${item}" '{ if (($1 == item) && ($2 ~ /(part|crypt|lvm|disk|md|raid)/ ) ) print $3}' | sort -ug | tail -1 )"
    if [[ -n "$fs" ]] ; then
        echo "$fs"
    fi
}
#get_filesystem_hal(){
    #local udi
    ##actually the only used
    ##/etc/init.d/dbus restart 1>/dev/null 2>&1
    ##/etc/init.d/hal restart 1>/dev/null 2>&1
    #udi=$( LC_ALL="$EL_LC_EN" hal-find-by-property --key "block.device" --string "$1" 2>/dev/null )
    #hal-get-property --udi "$udi" --key "volume.fstype" 2>/dev/null
#}

get_filesystem_file(){
    local ret part
    part="$1"

    ret="$(file -Ls "$part" )"

    case "$ret" in
        *HFS*|*hfs*)
            echo "hfsplus"
            ;;
        *"x86 boot sector"*"0xee"*|*"DOS/MBR boot sector"*"0xee"*)
            # this is raw / entire disks
            echo "disk"
            ;;
        *extended\ partition\ table*|*"ID=0x5"*)
            # Note: I have a result like this which looks to be wrong, it is not an extended partition, but in any case is not an usable one:  /dev/sdb: sticky x86 boot sector; partition 1: ID=0xee, starthead 0, startsector 1, 1953525167 sectors, extended partition table (last)\011, code offset 0x0
            # Note: ID=0x5 are represented for extended partitions over a GPT structure, but also are considered /dev/sda as disks, in any case since they are "layers" but not partitions is better to not have them showing up
            echo "extended"
            ;;
        *ext3*)
            echo "ext3"
            ;;
        *ext2*)
            echo "ext2"
            ;;
        *"ReiserFS V3"*)
            echo "reiserfs"
            ;;
        *XFS*)
            echo "xfs"
            ;;
        *ntfs*|*NTFS*|ntfs-3g)
            echo "ntfs-3g"
            ;;
        *vfat*|*FAT*)
            echo "vfat"
            ;;
        *swap*)
            echo "swap"
            ;;
        *btrfs*|*BTRFS*)
            echo "btrfs"
            ;;
        *)
            if [[ -x "$(which fdisk)" ]] ; then
                item_hd="$( get_disk_from_partition_complex "$item" )"

                if LC_ALL=C fdisk -l "${item_hd}" 2>/dev/null | grep -qs "^${part}.*BIOS boot" ; then
                    echo "BIOS"
                else
                    if LC_ALL=C fdisk -l "${item_hd}" 2>/dev/null | grep -qsE "^${part}\s+.*Extended$" ; then
                        echo "extended"
                    else
                        el_debug "unknown FS for $part"
                    fi
                    #echo "auto"
                fi
            fi
            ;;
    esac
}

get_filesystem_sfdisk(){
    local ret
    if [[ "$1" = /dev/nvme*p* ]] ; then
        ret="$(sfdisk "${sfdisk_print_id}" $( echo "$1" | sed 's/n[0-9]/ &/') 2>/dev/null )"
        if [[ -z "$ret" ]] ; then
            ret="$(sfdisk "${sfdisk_print_id}" $( echo "$1" | sed -e 's/n[0-9]/ &/' -e 's| p| |g' ) 2>/dev/null )"
        fi
    else
        if [[ "$1" = /dev/mmcblk*p* ]] || [[ "$1" = /dev/md*p* ]] || [[ "$1" = /dev/nbd*p* ]] ; then
            ret="$(sfdisk "${sfdisk_print_id}" $( echo "$1" | sed 's/p[0-9]/ &/') 2>/dev/null )"
            if [[ -z "$ret" ]] ; then
                ret="$(sfdisk "${sfdisk_print_id}" $( echo "$1" | sed -e 's/p[0-9]/ &/' -e 's| p| |g' ) 2>/dev/null )"
            fi
        else
            ret="$(sfdisk "${sfdisk_print_id}" $( echo "$1" | sed 's/[0-9]/ &/') 2>/dev/null )"
        fi
    fi

    # force mode
    if [[ -z "$ret" ]] ; then
        if [[ "$1" = /dev/nvme*p* ]] ; then
            ret="$(sfdisk --force "${sfdisk_print_id}" $( echo "$1" | sed 's/n[0-9]/ &/') 2>/dev/null )"
            if [[ -z "$ret" ]] ; then
                ret="$(sfdisk --force "${sfdisk_print_id}" $( echo "$1" | sed -e 's/n[0-9]/ &/' -e 's| p| |g' ) 2>/dev/null )"
            fi
        else
            if [[ "$1" = /dev/mmcblk*p* ]] || [[ "$1" = /dev/md*p* ]] || [[ "$1" = /dev/nbd*p* ]] ; then
                ret="$(sfdisk --force "${sfdisk_print_id}" $( echo "$1" | sed 's/p[0-9]/ &/') 2>/dev/null )"
                if [[ -z "$ret" ]] ; then
                    ret="$(sfdisk --force "${sfdisk_print_id}" $( echo "$1" | sed -e 's/p[0-9]/ &/' -e 's| p| |g' ) 2>/dev/null )"
                fi
            else
                ret="$(sfdisk --force "${sfdisk_print_id}" $( echo "$1" | sed 's/[0-9]/ &/') 2>/dev/null )"
            fi
        fi
    fi

    #   if [ "$?" != "0" ]; then
    #      echo "auto"
    #         return 0
    #      fi

    case "$ret" in
        1|4|6|b|c|e|14|16|1b|1c|1e|ef)
            echo "vfat"
            ;;
        7|17|86|87)
            echo "ntfs-3g"
            ;;
        #5|f|85|ee|ef|fd)
            #echo "blacklisted"
            #;;
        #ef)
            #echo "efi"
            #;;
        af)
            echo "hfsplus"
            ;;
        #*)
            #echo "auto"
            #;;
    esac
}



#
#  MAIN
#
main "$@"

# vim: set foldmethod=marker :
