#!/bin/bash
###############################################################################
# 
# MountPilot & sumo backend control script
# 
# Copyright (c) 2024-2026 Michel Mehl.
# All rights reserved. 
# Tous droits réservés (France).
# 
# License terms written down in file LICENSE.txt
# Les termes de la licence sont détaillés dans le fichier LICENSE.txt
# 
# Release file path: sumo
# Release file date: 2026-05-08 15:10
# Software product version: 2.0.2
# Source file last modification: 2026-05-08 12:09:19.576315179 +0000
#
# This header was generated. Do not modify.
#
# ------------------------------------------------------------------------------
#
# type 'man sumo' for further information.
#
# Sumo can also be used from another script and not as main app
# To invoke it from another script:
#
# source <sumo script>
# Sumo__main <usual script arguments>
#
# Main commands used:
#   mount, umount, mkfs.<fstype>, blkid, lsblk, awk, sudo, dd
#
# Package deps: (sudo dpkg -S <command> to retrieve package)
#   cryptsetup-bin      LUKS
#   veracrypt-console   VERA
#
# ------------------------------------------------------------------------------
# 
# Report bugs and suggestions: 
#     assistance@slashetc.fr
# 
# Specific or corporate requirements or extensions: 
#     info@slashetc.fr
# 
# The author is overall not required to provide maintenance or support 
# outside specific commercial terms agreed.
# 
###############################################################################

declare -A SUMO__VARS
SUMO__VARS["SUMO__MY_DIR"]=$(readlink -f $(dirname ${BASH_SOURCE[0]}))

#__LOG_DEBUG__=0

# The following vars are available after sourcing shell-api-core.sh
# __SHELL_CURRENT_APPNAME__
# __SHELL_SRC_NAME__
# Check _initShellApi documentation for further infos.
source "${SUMO__VARS["SUMO__MY_DIR"]}/shell-api/shell-api-core.sh" "Sumo"

# PERF TEST BEGIN
# Use this to assess performance of external file loading. Uncomment linked line below too.
# --> Normal usage: 0 to 1s
#Date__startTimer SUMO_loadModulesDepTimer

# Load dependency scripts
eval $_loadm<<<'shell-api-sys'
eval $_loadm<<<'shell-api-dev'
eval $_loadm<<<'shell-api-packing'
eval $_loadm<<<'shell-api-net'
eval $_loadm<<<'shell-api-yaml'
#eval $_loadm<<<'shell-api-selftest'
source "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__vars.sh" 
source "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__help.sh" 
source "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__network.sh" 
source "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__cloud.sh" 
source "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__vera.sh" 
source "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__virt.sh" 
source "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__luks.sh" 
source "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__overlay.sh" 
source "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__usb.sh" 

# PERF TEST END
# Uncomment to assess performance of external file loading. Uncomment linked line above too.
#Date__elapsedSecondsTimer $SUMO_loadModulesDepTimer secs show

export PATH=$PATH:/sbin/

:<<'EOF'
testadb=""
Sumo__usb_getMountpoint 0 testadb
echo "$testadb"
exit 0
EOF

:<<'EOF'
Retrieves the ancestry information regarding network devices. 
Based on the findmnt output, it returns for each device a string of the form

<mountpoint> <type> ..... <grand parent of device> <parent of device> <device>

Spaces are escaped with '§' char.
EOF

getNetworkDeviceAncestry()
{
        findmnt -o SOURCE,FSTYPE,TARGET| \
        awk -F' ' \
        -i "${SUMO__VARS["SUMO__MY_DIR"]}/awk-api/awk-api-core.awk"  \
        '{ 
                fstype=trim($2) 
                if (Net__isUNC($1) || Net__isLogin($1) || Net__isFTP($1) || Net__isNFS($1)) 
                {  
                        mntp=""; 
                        if(NF > 2) 
                        { 
                                mntp=sprintf("%s",$3) ; 
                                for(i=4;i<=NF;i++)
                                        mntp=sprintf("%s %s",mntp,$i); 
                        }
                        if (length(mntp)==0) 
                                mntp="-"
                        gsub(" ","§", mntp)
                        gsub(/^'${SUMO__VARS["LSBLK_TREE_CHARS"]}'+/,"",mntp)
                        printf("\"%s\" %s %s\n", mntp,$2,$1)  
                }  
        }' 
}

:<<'EOF'
Retrieves the ancestry information regarding block devices. 
Based on the lsblk output, it returns for each device a string of the form

<mountpoint> <type> ..... <grand parent of device> <parent of device> <device>

Spaces are escaped with '§' char.
EOF
getDeviceAncestry()
{
        lsblk --paths -o NAME,TYPE,MOUNTPOINT | awk "${SUMO__VARS["AWK_LSBLK_TREE_FLATTENING_CMD"]}" 
}

:<<'EOF'
Shows information on the current configured device in the same format as in a list.
Typically, this function is called after a mount/unmount operation.

Note that the ancestry information of the device is not regarded for the display, thereby
no indentation giving a hint on the hierarchical index. 
As a side effect, when a disk file is mounted, the actual filename may not be displayed as source,
but the actual system device which is mounted. Typically, this is the case for encrypted file volumes
like VERA and LUKS.
EOF

Sumo__listCurrentDevice()
{
        _log_dbg "Sumo__listCurrentDevice"
        local explicitDevice=""
        if [ $# -eq 1 ] ; then explicitDevice="$1" ; fi

        if [ -z "${SUMO__VARS["SILENT"]}" ] && [ -z "${SUMO__VARS["INTERACTIVE"]}" ]  ; then 
                SUMO__VARS["NO_HEADER"]=1
                SUMO__VARS["SHOW_FILTER_IN_SRC_COL"]=false
                local savedImgFile="${SUMO__VARS["IMG_FILE"]}"

                if Sumo__isVirt || [ ! -z "${SUMO__VARS["IMG_DISK_FILE_PATH"]}" ] ; then
                        if [ ! -z "${explicitDevice}" ] ; then
                                SUMO__VARS["IMG_FILE"]="${explicitDevice}"
                        else
                                SUMO__VARS["IMG_FILE"]="${SUMO__VARS["DEV"]}"
                        fi
                        Sumo__list noclear noancestry
                else
                        #SUMO__VARS["NO_HEADER"]=0
                        local allDevparts=(${SUMO__VARS["DEVPART"]})
                        local cnt=0
                        while [ $cnt -lt ${#allDevparts[@]} ] ; do
                                if ! Str__startsWith "${allDevparts[$cnt]}" "VG:" ; then
                                        SUMO__VARS["IMG_FILE"]="${allDevparts[$cnt]}"
                                        Sumo__list noclear noancestry
                                fi
                                cnt=$(($cnt + 1))
                        done    
                fi
                SUMO__VARS["IMG_FILE"]="$savedImgFile"
        fi
}

:<<'EOF'
Because the use of AVAIL,SIZE,USED may block findmnt on broken connnections, 
this function is in charge for testing each device to find the one which causes the blocking. 
When found, the size, used, avail field are set to empty and the first size field is set to "stuck",
which can be processed afterwards to identify and handle properly the stuck device.
Note:  
EOF

Sumo__list_resolveBlockingMounts()
{
        _log_dbg "Sumo__list_resolveBlockingMounts"

        local oldLsblk="${SUMO__VARS["OLD_LSBLK"]}"
        local mntInfos=""
        local singleMntInfo=""
        local findmntFields="$1"
        local reducedFindmntFields="LABEL,FSTYPE,SOURCE,OPTIONS,TARGET"
        declare -A sourceProcessed

        # Get list of all sources
        local mntSources=($(findmnt -n -o SOURCE ${SUMO__VARS["IMG_FILE"]}))
        if [ $? -ne 0 ] ; then
                _exit -10 "Sorry, unable to proceed further. findmnt gets blocked for more than 2s."
        fi
        #_log_dbg "!!! 'all sources ${mntSources[@]}'"

        # Find data for each source step by step 
        for mntSource in "${mntSources[@]}"
        do
        #_log_dbg "processing source '$mntSource'"
                singleMntInfo=""
                if [ -z "${sourceProcessed["$mntSource"]}" ] ; then
                        singleMntInfo=$(timeout -s SIGKILL 1 findmnt -n --pairs -o ${findmntFields} --source "$mntSource")
                        if [ $? -ne 0 ] ; then
                                # For FS types cifs and fuse.ssh, it seems the use of AVAIL,SIZE,USED can be block findmnt on broken connnections
                                singleMntInfo=$(timeout -s SIGKILL 1 findmnt --source "$mntSource" -n --pairs -o ${reducedFindmntFields})
                                # Insert manually empty fields for  AVAIL,SIZE,USED 
                                if [ $? -eq 0 ] ; then
                                        # If managed to get reduced list, add the missing infos and set to 0
                                        # On timeout, findmnt will return infos but without SIZE. So insert it here
                                        # taking advantage to set it to "stuck" for further processing
                                        if [ "${SUMO__VARS["OLD_LSBLK"]}" = "y" ] ; then
                                                singleMntInfo=$(echo "$singleMntInfo" | \
                                                        sed 's/" FSTYPE=/" SIZE="stuck" FSTYPE=/g' \
                                                        )
                                        else
                                                singleMntInfo=$(echo "$singleMntInfo" | \
                                                        sed 's/" FSTYPE=/" SIZE="stuck" FSTYPE=/g' | \
                                                        sed 's/" OPTIONS=/" SIZE="" USED="" AVAIL="" OPTIONS=/g' \
                                                        )
                                        fi
                                #else
                                #       return 1
                                fi
                        fi

                        sourceProcessed["$mntSource"]="done"
                fi

        #_log_dbg        "!!! ADDING '$singleMntInfo'"
                if [ ! -z "$singleMntInfo" ] ; then
                        mntInfos="$mntInfos
$singleMntInfo"
                fi
                Term__updateProgressBar "sumo_hang_con" "${#mntSources[@]}" 1  >&2
        done
        echo >&2
        echo "$mntInfos"
        return 0
}

:<<'EOF'
Main function used for listing the available devices, their respective data columns including mounting states
All parameters are forwarded to Sumo__list_setup. See parameter description there.
EOF

Sumo__list()
{
        _log_dbg "Sumo__list"
        Sumo__list_setup $*
        Sumo__list_manageDisplay
}

:<<'EOF'
This function is responsible for setting up the mount list, their respective data columns including mounting states

@param [1] control parameter. Possible values
           noclear: the screen is not cleared in interactive mode
           plain: the screen remains unchanged before displaying the actual list.
           By default, the screen is cleared in interactive mode and a new line is displayed otherwise, except if this script 
           was itself called in nested calls.
EOF

Sumo__list_setup()
{
        _log_dbg "Sumo__list_setup , file? '${SUMO__VARS["IMG_FILE"]}'"
        
        # Enter private mode in interactive mode
        if [ ! -z "${SUMO__VARS["INTERACTIVE"]}" ]  ; then
                if  ${SUMO__VARS["DISABLE_HISTORY"]} ; then
                        _exit -89 "Running interactive console with a positive filter is not supported. Use sumo -l ${SUMO__VARS["DEVTYPE"]} instead."
                fi
                if [ $# -eq 0 ]  ; then
                   Term__enterPrivateBufferMode
                fi
                Term__maskCursor        # Discard echoing and cursor while working
        fi

        if [ $# -eq 1 ] && [ "$1" == "plain" ] ; then
                :
        elif [ $# -eq 1 ] && [ "$1" == "noclear" ] ; then
                if [ ! -v SUMO__VARS["CALLER"] ] ; then printf "\n" ; fi
        elif [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] && [ ! -v SUMO__VARS["INTERACTIVE"] ] ; then
                if [ ! -v SUMO__VARS["CALLER"] ] ; then printf "\n" ; fi
        elif [ -v SUMO__VARS["INTERACTIVE"] ] ; then
                clear -x # clear terminal without loosing scrollback
        else
                if [ ! -v SUMO__VARS["CALLER"] ] ; then printf "\n" ; fi
        fi

        local sourceColTitle="Source"
        if ${SUMO__VARS["SHOW_FILTER_IN_SRC_COL"]} ; then
                local allFilters=${SUMO__VARS["DEVTYPE"]}
                allFilters=${allFilters// /}
                sourceColTitle="${sourceColTitle}§(${allFilters})"
        fi
        colsTitles=(Label "HW/Part" Size Avail FS Boot ${sourceColTitle} § Mountpoint)
        colsTitleAsString="${colsTitles[@]}"

        # Some old systems do not recognize --tree, which is default. So do not use.
        # Also , FSSIZE, FSUSED and FSAVAIL may not be available on older systems
        #local fullScanAncestry="$(lsblk --paths -o NAME,TYPE| awk '/^\/[A-Za-z]/{d0=$1; print $NF,d0};/^[└─├─]/{d1=$1; print $NF,d0, d1};/^  [└─├─]/{d2=$1; print $NF,d0, d1, d2}' | sed 's/[├─└─]//g')"
        # added for older system: last sed , chars | and ` in the awk expresion. It should not harm newer ones. A
        #local fullScanAncestry="$(lsblk --paths -o NAME,TYPE,MOUNTPOINT ${SUMO__VARS["IMG_FILE"]} |  \
        #awk "${SUMO__VARS["AWK_LSBLK_TREE_FLATTENING_CMD"]}" | \
        #sed 's/'${SUMO__VARS["LSBLK_TREE_CHARS"]}'//g'| sed 's/ -/ /g')"
#awk '/^\/[A-Za-z]/{d0=$1; print $NF,d0};/^'${SUMO__VARS["LSBLK_TREE_CHARS"]}'/{d1=$1; print $NF,d0, d1};/^  '${SUMO__VARS["LSBLK_TREE_CHARS"]}'/{d2=$1; print $NF,d0, d1, d2}'| 

        local fullScanAncestry=""
        if [ $# -eq 2 ] && [ "$2" == "noancestry" ] ; then
              fullScanAncestry=""
        else
              fullScanAncestry="$(getDeviceAncestry)"
        fi
        local netScanAncestry="$(getNetworkDeviceAncestry)"
        #echo "'$netScanAncestry'"
        #exit 0
        fullScanAncestry="$fullScanAncestry
$netScanAncestry"
#        echo "$fullScanAncestry"
       if [ -z "${SUMO__VARS["OLD_LSBLK"]}" ] ; then
                /bin/lsblk -o FSSIZE,FSUSED,FSAVAIL &>/dev/null
                if [ $? -eq 0 ] ; then  
                        SUMO__VARS["OLD_LSBLK"]="n"
                else
                        SUMO__VARS["OLD_LSBLK"]="y"
                        SUMO__VARS["LSBLK_FIELDS"]="${SUMO__VARS["OLD_LSBLK_FIELDS"]}"
                        SUMO__VARS["FINDMNT_FIELDS"]="${SUMO__VARS["OLD_FINDMNT_FIELDS"]}"
                fi
        fi
        local oldLsblk="${SUMO__VARS["OLD_LSBLK"]}" # This allows to spare a call at next turn
        local lsblkFields="${SUMO__VARS["LSBLK_FIELDS"]}" 
        local findmntFields="${SUMO__VARS["FINDMNT_FIELDS"]}" 
        local dataDb=$(lsblk --pairs --paths -n -o ${lsblkFields} ${SUMO__VARS["IMG_FILE"]}| \
                sed -E 's/""/"-"/g' | sed -E 's#[A-Z]+="([^"]+)"#\1 |#g' )

        if [ $? -ne 0 ] ; then
                _log_err "Failed to get list of block devices with lsbkl tool."
                _log_err "Command : lsblk --pairs --paths -n -o ${lsblkFields} ${SUMO__VARS["IMG_FILE"]}"
                return 1
        fi
#echo "$dataDb"
        # 2 starting empty fields for device type and pkname                 
#               sed 's/'${SUMO__VARS["LSBLK_TREE_CHARS"]}'//g'|  
#echo "before checking list" >&2
        local mntInfos=""
        if [ "${SUMO__CURRENT_OPERATION}" == "list" ] ; then
#echo "timeout -k 0 -s SIGKILL 2 findmnt -n --pairs -o ${findmntFields} ${SUMO__VARS["IMG_FILE"]})"
#               echo "before checking list" >&2
                mntInfos=$(timeout -k 0 -s SIGKILL 2 findmnt -n --pairs -o ${findmntFields} ${SUMO__VARS["IMG_FILE"]})
                if [ $? -ne 0 ] ; then
                        _log "It looks like some mounted connection is not responding."
                        _log "Analysing and switching to degraded mode for the related connection(s).."
                        mntInfos=$(Sumo__list_resolveBlockingMounts "$findmntFields")
                fi
        else
                mntInfos=$(findmnt -n --pairs -o ${findmntFields} ${SUMO__VARS["IMG_FILE"]})
        fi
#echo "after  checking list $mntInfos" >&2

        local dataAdbDb=""

        if [ -z "${SUMO__VARS["IMG_FILE"]}" ]  ; then
                local _adbdevices=()
                local _adbdevicesUnauth=()
                local _adbdevicesUnauthStatus=()
                local _adbdevice=""
                Adb__listDevices _adbdevices _adbdevicesUnauth _adbdevicesUnauthStatus
                for _adbdevice in ${_adbdevices[@]} ; do
        #- | - | - | 97.9G | nfs4 | adb://usb:TABA91000000010313 | 97.9G | 15.9G | 77G | rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.0.95,local_lock=none,addr=192.168.0.12 |adb://usb:TABA91000000010313  | - | - | '
        #"TYPE,PKNAME,LABEL,SIZE,FSTYPE,NAME,FSSIZE,FSUSED,FSAVAIL,RO,MOUNTPOINT,PARTUUID,PARTTYPE"
        #adb://usb:${_adbdevices[0]}
                        if ! findmnt adbfs &> /dev/null; then
                                local  newAdbDbLine="- | - | ${_adbdevice} | - | - | adbfs | - | - | - | - | -  | - | - | "
                                if [ -z "$dataAdbDb" ] ; then
                                        dataAdbDb="$newAdbDbLine"
                                else
                                        dataAdbDb="$dataAdbDb
$newAdbDbLine"
                                fi
                        fi
                done
                local c=0
                while [ $c -lt ${#_adbdevicesUnauth[@]} ] ; do
                #for _adbdevice in ${_adbdevicesUnauth[@]} ; do
                        _adbdevice="${_adbdevicesUnauth[$c]}"
                        _adbdeviceStatus="${_adbdevicesUnauthStatus[$c]}"
                        #_log "'${_adbdevice}' '${_adbdeviceStatus}'"
                        if ! findmnt adbfs &> /dev/null; then
                                local  newAdbDbLine="- | - | ${_adbdevice} | - | - | adbfs ${_adbdeviceStatus}| - | - | - | - | -  | - | - | "
                                if [ -z "$dataAdbDb" ] ; then
                                        dataAdbDb="$newAdbDbLine"
                                else
                                        dataAdbDb="$dataAdbDb
$newAdbDbLine"
                                fi
                        fi
                        c=$(( $c + 1))
                done

        fi

        local dataFullNetDb=$(echo "$mntInfos"| \
                                sed -E 's/""/"-"/g' | \
                                sed -E 's#[A-Z]+="([^"]+)"#\1 |#g') 

        local dataNetDb=$(echo "$dataFullNetDb" | awk -F '|' \
                -i "${SUMO__VARS["SUMO__MY_DIR"]}/awk-api/awk-api-core.awk"  \
               '{ fstype=trim($3) ; addr=trim($4); if (Net__isUNC(addr) || Net__isLogin(addr) || Net__isFTP(addr) || Net__isHTTP(addr) || Net__isCloudDevice(addr) || USB__isAdbDevice(addr) || Net__isNFS(addr) || (fstype == "overlay") ) { print "- | - |",$0 } }') 

#echo "$dataFullNetDb"
#echo "$dataNetDb"
#echo "$dataAdbDb"
#echo "$fullScanAncestry"
#exit 0
        dataDb="$dataDb
$dataNetDb
$dataAdbDb"
#echo "'$dataDb'"
#echo "dataNetDb: '$dataNetDb'"
#exit 0
        # If there is no change in the DB do not proceed unnecessary further
        if [ "${SUMO__VARS["CACHE_LIST_DATA_DB"]}" != "$dataDb" ] ; then #|| ([ $# -eq 1 ] && [ "$1" == "force" ]) ; then
                SUMO__VARS["CACHE_LIST_DATA_DB"]="$dataDb"
                # Reset mount status only if rebuilding a new list
                Sumo__resetNotMountStatus # Mark all known items as not-mounted                
        else
                _log_dbg "LIST: UPDATE IGNORED SAME DATA !"
                return 0
        fi

        local list="$(echo "$dataDb" | \
                        LC_ALL=C.UTF-8 awk -F"|" \
                        -v OLDLSBLK="$oldLsblk" \
                        -v DISPLAY_FORMAT="${SUMO__VARS["DISPLAY_FORMAT"]}" \
                        -v comaSeparatedFilters="${SUMO__VARS["DEVTYPE"]}" \
                        -v lbl="${SUMO__VARS["FS_LABEL"]}" \
                        -v ancestry="${fullScanAncestry}" \
                        -v fullMountList="${dataFullNetDb}" \
                        -v allfstypes="${SUMO__VARS["SUMO__ALLFSTYPES"]}" \
                        -v allsoftdevtypes="${SUMO__VARS["SUMO__ALLSOFTDEVTYPES"]}" \
                        -v columnsTitles="${colsTitleAsString}" \
                        -v HOME="${HOME}" \
                        -v MAPPERDIR=${Dev__mapperdir} \
                        -v max_len_src_string=35 \
                        -v max_len_mntp_string=35 \
                        -v LOG_DEBUG="${__LOG_DEBUG__}" \
                        -v SUMO_DIR="${SUMO__VARS["SUMO__MY_DIR"]}" \
                        -i "${SUMO__VARS["SUMO__MY_DIR"]}/awk-api/awk-api-core.awk" \
                        -i "${SUMO__VARS["SUMO__MY_DIR"]}/awk-api/awk-api-dev.awk" \
                        -i "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__lib.awk" \
                        -f "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__list.awk")"
        #-v HOME="${HOME}" -v HOME_REPLACE="~${USER}"
        #list=$(Sumo__list_bash)
        #_log_dbg "$list"
        local headerInfo="$(head -n1 <<<"$list")"

        SUMO__CURRENT_LIST="$(tail -n+2 <<<"$list")"
        SUMO__CURRENT_LIST_WITHOUT_RECENT="${SUMO__CURRENT_LIST}"
        SUMO__CURRENT_RECENTLIST_SIZE=0         # computed later in Sumo__completeListWithHistory
        SUMO__CURRENT_LIST_SIZE=0               # computed in Sumo__setupRecentList
        if [ ${SUMO__LIST_LINE_WIDTH} -ne 0 ] ; then # There exists a value computed before, save it
                SUMO__PREV_LIST_LINE_WIDTH=${SUMO__LIST_LINE_WIDTH}
                SUMO__PREV_COLS_WIDTH="${SUMO__COLS_WIDTH}"
        fi
        SUMO__LIST_LINE_WIDTH="${headerInfo%% *}"        
        SUMO__LIST_LINE_WIDTH_WITHOUT_RECENT=${SUMO__LIST_LINE_WIDTH}
        SUMO__COLS_WIDTH="${headerInfo#* }"
        SUMO__COLS_WIDTH_WITHOUT_RECENT="${SUMO__COLS_WIDTH}"

#echo "after awk" >&2

        _log_dbg "line width='$SUMO__LIST_LINE_WIDTH' colwidth='$SUMO__COLS_WIDTH'"

# disk symbol echo $'\u26c1'
# usb cable echo $'\u257c'
# $'\U1F4C1' folder
# $'\U1F310' globus
# floppy $'\U1F4BE'
# optical disk $'\U1F4BF'

        if [ -z "${SUMO__VARS["IMG_FILE"]}" ]   ; then
                # Save the recent list 
                Sumo__setupRecentList

                # Add items of the recent list, this also updates the max cols width and line width
                # depending on the registered recent items
                Sumo__completeListWithHistory

                # Only actually save the recent list here
                if [ ! -z "${SUMO__VARS["INTERACTIVE"]}" ] ; then
                        if ! ${SUMO__VARS["HISTORY_GHOST"]} ; then
                                _saveRecentList
                        fi
                fi
        fi
}

:<<'EOF'
Main function for managing the display of the mount list depending on whether the interactive mode is on.
EOF

Sumo__list_manageDisplay()
{
        # Display table 
        if [  -z "${SUMO__VARS["INTERACTIVE"]}"  ] ; then
                Sumo__im_adaptTermSize
                Sumo__printList 0
                if [ ! -v SUMO__VARS["CALLER"] ] ; then printf "\n" ; fi
        else
                local curTermSize=($(stty size))
                SUMO__VARS["CURRENT_TERM_HEIGHT"]=${curTermSize[0]}
                SUMO__VARS["CURRENT_TERM_WIDTH"]=${curTermSize[1]} 

                Input__clearForcedInput
                Sumo__im_manageInteractiveMode
        fi
}

:<<'EOF'
In interactive mode, this function enables to adapt the terminal size according the 
number of rows and the maximum line width which are required to display the mount list.

By default, the number of rows required is equal to the number of items of the displayed
mount list plus an area of 14 lines at the bottom reserved for details and additional help.

It also clear the terminal content.
EOF

Sumo__im_adaptTermSize()
{
        local curSize=($(stty size))
        local targetNbRows
        local targetNbCols
        local nbMaxDetailsSectionLines="${SUMO__VARS["nbMaxDetailsSectionLines"]}"
        local nbDetailsSectionLines=${nbMaxDetailsSectionLines}
        #nbDetailsSectionLines=$((3 + ${nbDetailsSectionLines}))
        # For dynamic height depending on details, use ${SUMO__VARS["NB_SHOWN_DETAIL_LINES"]} instead of ${nbMaxDetailsSectionLines}

        targetNbCols=$((${SUMO__LIST_LINE_WIDTH}+3))
        Int__max ${SUMO__VARS["minTermLineWidth"]} ${targetNbCols} targetNbCols

        targetNbRows=$((1+${SUMO__CURRENT_LIST_SIZE} + 1)) 
        if [ ${SUMO__VARS["SHOW_HISTORY"]} -eq 0 ] ; then
                targetNbRows=$((${targetNbRows} + ${SUMO__CURRENT_RECENTLIST_SIZE} + 1 + 1))
        else
                targetNbRows=$((${targetNbRows} + 1))
        fi
        #echo "targetNbCols $targetNbCols vs ${curSize[1]} " >> dbg.txt # DEBUG

        #if [ ${SUMO__VARS["SHOW_DETAILS"]} -eq  0 ] ; then
                targetNbRows=$((${targetNbRows} + nbDetailsSectionLines))
        #fi
        #_log_dbg "Sumo__im_adaptTermSize: '${curSize[@]}', targetNbRows=$targetNbRows"
        if [ $targetNbRows -ne ${curSize[0]} ] || [ $targetNbCols -ne ${curSize[1]} ]  ; then
                # 1 x table col names) + list size + 1xkey shortcuts + detail: 1xempty+1x"details"+nb detail field+1xempty 
                if [ -z "${SUMO__VARS["INTERACTIVE"]}" ] ; then
                        # When not interactive mode, never reduce terminal width
                        local termWidth
                        Int__max $targetNbCols ${curSize[1]} termWidth
                        # When not interactive mode, keep terminal height as it was
                        local termHeight=${curSize[0]}
                        #_log_dbg "RESIZE to $termHeight $termWidth, initial size was ${curSize[0]} ${curSize[1]}"
                        #echo "RESIZE to $termHeight $termWidth, initial size was ${curSize[0]} ${curSize[1]}" >> ~dbg.txt
                        Term__resize $termHeight $termWidth
                        SUMO__VARS["CURRENT_TERM_HEIGHT"]=$termHeight
                        SUMO__VARS["CURRENT_TERM_WIDTH"]=$termWidth
                else
                        #_log_dbg "RESIZE to $targetNbRows $targetNbCols"
                        Term__clear                
                        Term__resize $targetNbRows $targetNbCols
                        SUMO__VARS["CURRENT_TERM_HEIGHT"]=$targetNbRows
                        SUMO__VARS["CURRENT_TERM_WIDTH"]=$targetNbCols
                fi
        else
                if [ ! -z "${SUMO__VARS["INTERACTIVE"]}"  ] ; then
                        tput cup 0 0 
                fi
        fi
}


Sumo__im_manageUnmount()
{
        local original_src="$1"
        local src="$2"
        local reqType="$3"
        local ghostOpt=""
        if ${SUMO__VARS["HISTORY_GHOST"]} ; then ghostOpt="--ghost" ; fi

        Sumo__im_resetBottomArea
        Input__confirm "There are some mounts bound with ${original_src}. Do you want to continue and first unmount?"
        local doUnmountBeforeFormatting=$?
        _log ""
        local mypid=0
        if [ $doUnmountBeforeFormatting -eq 0 ] ; then
                $0 ${ghostOpt} --caller="$mypid" -y -s -u -a "$src"  # src can be a delegate
                if [ $? -ne 0 ] ; then
                        Sumo__im_resetBottomArea
                        Sumo__im_manageTimedErrorMessage false "Unmount failed! ${reqType} aborted." 2
                        return 1
                fi

                local recentKey=${src// /§} # Escape spaces when used as keys to enable proper saving        
                SUMO__NOT_MOUNTED["$recentKey"]="${SUMO__CURRENT_ROW}"
                if Str__startsWith "$recentKey" "${Dev__mapperdir}" ; then
                        Sumo__eraseHistoryItem "$recentKey" false
                fi   

        else
                Sumo__im_resetBottomArea
                Sumo__im_manageTimedErrorMessage false "${reqType} operation aborted." 2
                return 1
        fi

        return 0
}

:<<'EOF'
In interactive mode, this function enables to clear the area at the bottom of the mount list.
The cursor is also reset and moved at the bottom of the mount list, at the position 
where the detailed infos and additional help will start to display.
EOF

Sumo__im_resetBottomArea()
{
        local nbLines=$((1+${SUMO__CURRENT_LIST_SIZE} + 1 + ${SUMO__CURRENT_RECENTLIST_SIZE} + 1 + 1 ))
        tput cup $nbLines 0
        tput ed
}

:<<'EOF'
Stops any running mounting monitoring. FIND_MNT_POLL_PID is reset to 0. 
EOF

Sumo__im_stopMountMonitoring()
{
        if [ ${SUMO__VARS["FIND_MNT_POLL_PID"]} -ne 0 ] ; then
                _log_dbg "stop PID ${SUMO__VARS["FIND_MNT_POLL_PID"]} "
                kill -SIGTERM ${SUMO__VARS["FIND_MNT_POLL_PID"]} &>/dev/null
                SUMO__VARS["FIND_MNT_POLL_PID"]=0
                SUMO__VARS["FDISK_POLL_DEV_LIST"]=""
        fi        
}

:<<'EOF'
Starts the mounting monitoring
EOF

Sumo__im_startMountMonitoring()
{
        Sumo__im_stopMountMonitoring

        local pollResultFile="$HOME/.local/sumo/poll.txt"
        stdbuf -o0 findmnt -n -o action,source,target,options --poll=umount,mount,remount  > ${pollResultFile} 2>>"${__LOG_ERR_FILE__}" & 
        SUMO__VARS["FIND_MNT_POLL_PID"]=$!
        _log_dbg "launch poll PID ${SUMO__VARS["FIND_MNT_POLL_PID"]}"
}

:<<'EOF'
Callback function invoked while waiting for input within 'Input__cursorSelect' function.
EOF

Sumo__im_inputTimeoutCallback()
{
        Sumo__im_printPromptLine

        if [ ${SUMO__VARS["FIND_MNT_POLL_PID"]} -eq 0 ] || ! Sys__isAlive ${SUMO__VARS["FIND_MNT_POLL_PID"]} ; then
                #_log "++++++++++ RESTARTING DEVICE POLL" # DEBUG
                Sumo__im_startMountMonitoring
                return 0
        else
                local pollResultFile="$HOME/.local/sumo/poll.txt"
                if [ -f "${pollResultFile}" ] ; then
                        local fileSize=$(stat -c "%s" ${pollResultFile} 2>>"${__LOG_ERR_FILE__}")
                        #_log_dbg "poll file size is '$fileSize'"

                        # If any new mounting occurred, force update of the list 
                        # by return 253
                        if [ $fileSize -gt 0 ] ; then
                                Sumo__im_startMountMonitoring
                                #_logf "Sumo__im_inputTimeoutCallback: new mount $(cat "$pollResultFile")"
                                # reread recent list
                                if ! _readRecentList ; then
                                        _log_warn "Failed to read recent list."
                                fi
                                # update list
                                return 253 
                        fi

                        # Moreover, if the list of known devices changed, force update of the list as well
                        local diskList="$(${__SUDO__}sfdisk -l -q -n -o Device,Type 2>>"${__LOG_ERR_FILE__}" |uniq)"
                        if [ ! -z "${SUMO__VARS["FDISK_POLL_DEV_LIST"]}" ] ; then
                                if [ "$diskList" != "${SUMO__VARS["FDISK_POLL_DEV_LIST"]}" ] ; then
                                        SUMO__VARS["FDISK_POLL_DEV_LIST"]="$diskList"
                                        #_logf "Sumo__im_inputTimeoutCallback: new device detected $diskList)"
                                        # reread recent list
                                        if ! _readRecentList ; then
                                                _log_warn "Failed to read recent list."
                                        fi
                                        # update list
                                        return 253
                                fi
                        else
                                SUMO__VARS["FDISK_POLL_DEV_LIST"]="$diskList"
                        fi
                fi
                return 0
        fi
}

Sumo__im_getListIndexesToIgnore()
{
        local lineEscapeMagic='\\'
        local line=""
        local lineIndex=1
        local -n out_ignoreIndexList=$1
        while IFS= read -r line
        do 
                #_log_dbg "Sumo__im_getListIndexesToIgnore '$line'"
                #printf "escape '%s'\n" "$lineEscapeMagic" >> ${__LOG_WARN_FILE__}
                if Str__startsWith "$line" "$lineEscapeMagic" ; then  
                        _log_dbg "FOUND escape '%s'\n" "$lineEscapeMagic" 
                        out_ignoreIndexList="$out_ignoreIndexList $lineIndex"; 
                fi
                #if Str__startsWith "$line" "/ignore" ; then  
                #        _log_dbg "FOUND escape '%s'\n" "$lineEscapeMagic" 
                #        out_ignoreIndexList="$out_ignoreIndexList $lineIndex"; 
                #fi

                lineIndex=$(($lineIndex+1))
        done <<< "${SUMO__CURRENT_LIST}"
        
        #printf "out_ignoreIndexList='%s'\n" "$out_ignoreIndexList" >> ${__LOG_WARN_FILE__}
}

Sumo__im_manageTimedErrorMessage()
{
        local isError=$1
        if $isError ; then
                _log_err "$2"
        else
                _log_warn "$2"
        fi
        Term__countdown "Continuing in " $3 " seconds"
}

:<<'EOF'
Erases an item of the recent list history given the source device
@param[1] source device path to remove from mount history
@param[2] boolean telling to save the list
EOF
Sumo__eraseHistoryItem()
{
        local src="$1"
        local save=$2
        local mountOpt="$3"
        #Sumo__list plain # this forces refreshing of SUMO__CURRENT_LIST

        if [ ! -z "$mntOpt" ] ; then
                # The recent key for overlays must be absolute paths
                Sumo__overlay_buildLogicalMountSourceFromMountOptions "$mountOpt" src true
        fi

        local recentKey=${src// /§} # Escape spaces when used as keys to enable proper saving        
        #_log_dbg "ERASE HISTORY for SUMO__RECENT["$recentKey"] "

        if [ -z "${SUMO__RECENT["$recentKey"]}" ] && [ ! -f "$src" ]; then
                local srcBasename=""
                File__basename "$src" srcBasename
                local searchSrc
                local foundSrc=()

                for searchSrc in "${!SUMO__RECENT[@]}" ; do
                        local searchSrcBasename=""
                        File__basename "$searchSrc" searchSrcBasename
                        #_log_dbg "src: '$src', srcBasename: '$srcBasename', searchSrc: '$searchSrc' , searchSrcBasename: '$searchSrcBasename'"
                        # We test also the basename to see if there's an item looking similar
                        if [ "$srcBasename" = "$searchSrcBasename" ] ; then
                                if [ ! -z "${SUMO__NOT_MOUNTED["$searchSrc"]}" ] ; then # it must also not be mounted
                                        foundSrc+=("$searchSrc")
                                fi
                        fi
                done
                #_log_high "FOUND SRC: ${foundSrc[@]}"
                local searchSrcFound=false
                Sumo__im_resetBottomArea                
                if [ ${#foundSrc[@]} -gt 0 ] ; then
                        _log_warn "The item selected for removal '$src' seems not to exist anymore."
                        for searchSrc in "${foundSrc[@]}" ; do
                                if Input__confirm "A close item is '$searchSrc'. Remove this one?" ; then
                                        src="${searchSrc}"
                                        recentKey=${searchSrc// /§}
                                        searchSrcFound=true
                                        _log ""
                                        break
                                fi
                                _log ""
                        done
                fi
                if ! $searchSrcFound ; then
                        local recentFilePath
                        __getRecentListFilePath recentFilePath               
                        _log_warn "The item selected for removal '$src' cannot be removed due to an inconsistency in the file paths recorded for this item in the recent file list."
                        _log_warn "Please quit mountpilot, fix or remove the item direcly in file '$recentFilePath'"
                        return 1
                fi
        fi

        SUMO__NOT_MOUNTED["$recentKey"]="${SUMO__CURRENT_ROW}"
        SUMO__RECENT["$recentKey"]=""
        unset SUMO__RECENT["$recentKey"]
        #SUMO__CURRENT_SELECT_INDEX=1
        SUMO__CURRENT_LIST="${SUMO__CURRENT_LIST_WITHOUT_RECENT}"
        Sumo__completeListWithHistory

        if $save ; then
                if ! ${SUMO__VARS["HISTORY_GHOST"]} ; then
                        _saveRecentList
                fi
        fi
}


:<<'EOF'
Manages the interactive mode by handling the key strokes
EOF

Sumo__im_manageInteractiveMode()
{
        Term__clear
        Sumo__im_adaptTermSize

        while [ ! -z "${SUMO__VARS["INTERACTIVE"]}"  ] ; 
        do

        Term__maskCursor
        printf '\033[s' 

        local currentSelectionIndex=${SUMO__CURRENT_SELECT_INDEX} # 1 by default at first time

        # Determine the indexes of the lines starting with \\ to ignore
        local ignoreIndexList=""
        Sumo__im_getListIndexesToIgnore ignoreIndexList

        local keyShortcutsConfig="${SUMO__VARS["KEY_SHORTCUTS"]}" #"d:255,r:64+?,u:253,i:252,b:251,e:250,h:249"

        #        _log_dbg "manage interactive' $SUMO__CURRENT_SELECT_INDEX >  ${SUMO__CURRENT_LIST_SIZE} ?"                
        #        _log_dbg "keyShortcutsConfig: $keyShortcutsConfig. currentselect:'${SUMO__CURRENT_SELECT_INDEX}' size='${SUMO__CURRENT_LIST_SIZE}'"

        # The prompt is actually not displayed, since a print callback is specified, meaning all  display is taken over by this script        
        local monitoringCallbackName=""
        if [ ${SUMO__VARS["MONITORING_TIME"]} -gt 0 ] ; then
                monitoringCallbackName="Sumo__im_inputTimeoutCallback ${SUMO__VARS["MONITORING_TIME"]}"
        fi
        local _errlog
        _getLogErrPath _errlog

        local ghostOpt=""
        if ${SUMO__VARS["HISTORY_GHOST"]} ; then ghostOpt="--ghost" ; fi

        Input__cursorSelect \
                "${SUMO__CURRENT_LIST}" \
                "" \
                $currentSelectionIndex \
                Sumo__printList \
                "" \
                "$keyShortcutsConfig" \
                "$ignoreIndexList" \
                "$monitoringCallbackName"
        local index=$?
        #_log_dbg "index: '$index' '$keyShortcutsConfig'"

        if [ $index -ne 0 ] ; then                        
                if [ $index -eq 249 ] ; then
                                #_log_warn "HELP KEY HISTORY ${SUMO__CURRENT_RECENTLIST_SIZE}"
                                if [ ${SUMO__VARS["SHOW_HISTORY"]} -eq 0 ] ; then
                                        if [ ${SUMO__CURRENT_RECENTLIST_SIZE} -gt 0 ] ; then
                                                SUMO__VARS["SAVED_COLS_WIDTH"]="${SUMO__COLS_WIDTH}"
                                                SUMO__VARS["SAVED_LIST_LINE_WIDTH"]=${SUMO__LIST_LINE_WIDTH}
                                                SUMO__VARS["SHOW_HISTORY"]=1

                                                SUMO__CURRENT_LIST="${SUMO__CURRENT_LIST_WITHOUT_RECENT}"
                                                SUMO__LIST_LINE_WIDTH=${SUMO__LIST_LINE_WIDTH_WITHOUT_RECENT}
                                                SUMO__COLS_WIDTH="${SUMO__COLS_WIDTH_WITHOUT_RECENT}"
                                                if [ ${SUMO__LIST_LINE_WIDTH} -ne 0 ] ; then # There exists a value computed before, save it
                                                        SUMO__PREV_LIST_LINE_WIDTH=${SUMO__LIST_LINE_WIDTH}
                                                        SUMO__PREV_COLS_WIDTH="${SUMO__COLS_WIDTH}"
                                                fi
                                                # Reajust current index if pointing to an history item
                                                if [ ${SUMO__CURRENT_SELECT_INDEX} -gt ${SUMO__CURRENT_LIST_SIZE} ] ; then
                                                        currentSelectionIndex=${SUMO__CURRENT_SELECT_INDEX}
                                                fi
                                        fi

                                        Sumo__im_adaptTermSize
                                        continue
                                else
                                        SUMO__VARS["SHOW_HISTORY"]=0
                                        SUMO__COLS_WIDTH="${SUMO__COLS_WIDTH_WITHOUT_RECENT}"
                                        SUMO__LIST_LINE_WIDTH="${SUMO__LIST_LINE_WIDTH_WITHOUT_RECENT}"
                                        Sumo__completeListWithHistory
                                        Sumo__im_adaptTermSize
                                        continue
                                fi

                # More infos/help
                elif [ $index -eq 252 ] ; then
                        if [ -z ${SUMO__LIST_CURRENT_HELP_CALLBACK} ] ; then
                                local hwType=$(echo "${SUMO__CURRENT_ROW}"|awk -F ' ' '{print $2}')
                                if Str__startsWith "$hwType" "WIFI" ; then
                                        #printf '\033[u' 
                                        SUMO__LIST_CURRENT_HELP_CALLBACK=Sumo__help_wifi
                                elif Str__startsWith "$hwType" "USB" ; then
                                        #printf '\033[u' 
                                        SUMO__LIST_CURRENT_HELP_CALLBACK=Sumo__help_usb
                                elif Str__contains "$hwType" "BASE-T" ; then
                                        if Env__fn_exists "Sumo__help_${hwType}" ; then
                                                #printf '\033[u' 
                                                SUMO__LIST_CURRENT_HELP_CALLBACK="Sumo__help_${hwType}" 
                                        fi
                                fi
                        else
                                SUMO__LIST_CURRENT_HELP_CALLBACK=""
                        fi
                # Logs
                elif [ $index -eq 244 ] ; then
                        if [ -z ${SUMO__LIST_CURRENT_HELP_CALLBACK} ] ; then
                                SUMO__LIST_CURRENT_HELP_CALLBACK=Sumo__help_showLog
                        else
                                SUMO__LIST_CURRENT_HELP_CALLBACK=""
                        fi
                # Update                        
                elif [ $index -eq 253 ] ; then
                        # update
                        printf '\033[u' 
                        printf '\033[f' # ensure cursor is at the top
                        #tput cup 0 0
                        #tput ed
                        #Sumo__list plain # this forces refreshing of SUMO__CURRENT_LIST                        
                        Sumo__list_setup plain
                        Sumo__im_adaptTermSize
                        continue
                # Switch on/off details
                elif [ $index -eq 255 ] ; then
                        SUMO__VARS["SHOW_DETAILS"]=$(( ~ ${SUMO__VARS["SHOW_DETAILS"]} ))
                        printf '\033[u' 
                        Sumo__im_adaptTermSize
                        #printf '\033[f' # ensure cursor is at the top

                        #if [ ${SUMO__VARS["SHOW_DETAILS"]} -ne 0 ] ; then
                        #        clear -x
                        #fi
                else
                        printf '\033[u' 
                        Term__restoreCursor # Ensure cursor is visible

                        local operationResult=0
                        local doRemount=1
                        local originalIndex="$index"
                        #_logf "===> INDEX ?? '${index}'" # FOR DEBUG
                        if [ $index -gt 64 ] ; then
                                index=$(($index - 64))
                                doRemount=0
                        fi
                        printf '\n'
                        local mntp="" 
                        local mntp_realpath=""
                        local src="" 
                        local original_src=""
                        local status=""

                        # Specific states
                        local ro=1
                        local notmountable=1
                        local statusMountStuck=false
                        local nolink=1                        
                        local delegate_device=""
                        local delegate_mntp=""
                        local delegate_status=""
                        local hasMountedChild=""
                        local embeddingdiskfilePath
                        local isNetworkLink=""
                        local formatAllowed="no"
                        local devLabel=""
                        local mountOpt=""
                        Sumo__list_decodeHiddenData "${SUMO__CURRENT_ROW}" SUMO_DETAIL_HIDDEN_DATA_MAP SUMO_DETAIL_RANKS_DATA_MAP

                        # NOTE fields starting with '/' are not shown in the detailed information at the bottom
                        #
                        devLabel="${SUMO_DETAIL_HIDDEN_DATA_MAP["label"]}"
                        formatAllowed="${SUMO_DETAIL_HIDDEN_DATA_MAP["format"]}"                        # This indicates it is a physical disk
                        isNetworkLink="${SUMO_DETAIL_HIDDEN_DATA_MAP["/is network link"]}"
                        embeddingdiskfilePath="${SUMO_DETAIL_HIDDEN_DATA_MAP["embedding disk file path"]}"
                        hasMountedChild="${SUMO_DETAIL_HIDDEN_DATA_MAP["/has-mounted-child"]}"
                        delegate_device="${SUMO_DETAIL_HIDDEN_DATA_MAP["/delegate-device"]}"
                        delegate_mntp="${SUMO_DETAIL_HIDDEN_DATA_MAP["/delegate-mountpoint"]}"
                        delegate_status="${SUMO_DETAIL_HIDDEN_DATA_MAP["/delegate-status"]}"
                        mntp="${SUMO_DETAIL_HIDDEN_DATA_MAP["mountpoint"]}"
                        mntp_realpath="${SUMO_DETAIL_HIDDEN_DATA_MAP["mountpoint_realpath"]}"
                        src="${SUMO_DETAIL_HIDDEN_DATA_MAP["/mountsource"]}"
                        original_src="$src"
                        status="${SUMO_DETAIL_HIDDEN_DATA_MAP["status"]}"
                        recentdate="${SUMO_DETAIL_HIDDEN_DATA_MAP["/recent"]}"
                        mountOpt="${SUMO_DETAIL_HIDDEN_DATA_MAP["mount options"]}"
                        local srcIsDelegate=false


                        #for dbg_key_data in "${!SUMO_DETAIL_HIDDEN_DATA_MAP[@]}" ; do _logf "${dbg_key_data}: ${SUMO_DETAIL_HIDDEN_DATA_MAP[${dbg_key_data}]}" ; done
                        #sleep 10

                        if [ ! -z "$mntp_realpath" ] ; then mntp="$mntp_realpath" ; fi

                        if [ "$mntp" == "-" ] ; then mntp="" ; fi
                        if [ "$devLabel" == "-" ] ; then devLabel="" ; fi

                        #_log_dbg "INDEX='$index' RAW SRC '$src' mntp='$mntp'"

                        local mypid=0
                        if [ $originalIndex -ne 248 ] &&  [ $originalIndex -ne 250 ] ; then 
                                # Mount/unmount action delegation is not relevant
                                # for 'erase history' and 'assign label' actions which must be applied 
                                # directly to the selected item
                                if [ ! -z "${delegate_device}" ] ; then
                                        src="${delegate_device}"
                                        srcIsDelegate=true
                                fi
                                if [ ! -z "${delegate_mntp}" ] ; then
                                        mntp="${delegate_mntp}"
                                fi
                                if [ ! -z "${delegate_status}" ] ; then
                                        if [ "${delegate_status}" == "0" ] ; then
                                                status="read-write"
                                        else
                                                status="read-only"
                                        fi
                                fi
                        fi

                        if [ "$status" == "read-only" ] ; then ro=0 ; else ro=1; fi
                        if [ "$status" == "not mountable" ] ; then notmountable=0 ; fi  
                        if [ "$status" == "stuck" ] ; then statusMountStuck=true ; fi  

                        if [ $notmountable -ne 0 ] ; then
                                if  [ ! -z "${SUMO_DETAIL_HIDDEN_DATA_MAP["full disk file path"]}" ] ; then 
                                        src="${SUMO_DETAIL_HIDDEN_DATA_MAP["full disk file path"]}" 
                                        srcIsDelegate=false
                                elif [ ! -z "${SUMO_DETAIL_HIDDEN_DATA_MAP["/real source"]}" ] ; then 
                                        src="${SUMO_DETAIL_HIDDEN_DATA_MAP["/real source"]}" 
                                        srcIsDelegate=false
                                fi
                        fi 

                        if Str__contains "$mountOpt" "upperdir=" ; then
                                Sumo__overlay_buildLogicalMountSourceFromMountOptions "$mountOpt" src true
                        fi

                        # 'nolink' is used both to handle the similar case where connection is lost at the source
                        # or when connection is stuck
                        if $statusMountStuck || [ "${SUMO_DETAIL_HIDDEN_DATA_MAP["link_detected"]}" == "no" ] ; then 
                                nolink=0 
                        fi
                        
                        # FOR DEBUG
                        #_logf "->> doRemount? '${doRemount}' nolink='${nolink}', statusMountStuck=${statusMountStuck}, link_detected set?? '${SUMO_DETAIL_HIDDEN_DATA_MAP["link_detected"]}'"

                        # Ensure src is always without quotes always
                        Str__trimOnce "$src" src "\"" 
                        Str__trimOnce "${embeddingdiskfilePath}" embeddingdiskfilePath "\""

                        # _log_dbg "manage interactive' originalIndex=$originalIndex $SUMO__CURRENT_SELECT_INDEX >  ${SUMO__CURRENT_LIST_SIZE} ?"        

                        if [ $originalIndex -eq 248 ] ; then
                                # Label cannot be assigned to a not mounted device
                                if [ ! -z "$recentdate" ] ; then
                                        continue
                                fi
                                tput ed
                                # Change label
                                local entered_label=""
                                local fstype=$(lsblk -n -o FSTYPE "${original_src}" 2>/dev/null)
                                # Filter error cases
                                if [ $? -ne 0 ] ; then                 
                                        Sumo__im_manageTimedErrorMessage false "Impossible to assign label to device $original_src" 2
                                        continue
                                fi
                                # Filter what fstype not supported               
                                case "$fstype" in 
                                        ext2|ext3|ext4|ntfs|exfat|vfat) ;;
                                        *) 
                                                Sumo__im_manageTimedErrorMessage false "Assigning a label to device ${original_src} is not supported. It must be any fs among ext2,ext3,ext4,ntfs,exfat,vfat." 2
                                                continue
                                        ;;
                                esac
                                # Manage label entry
                                if Input__Word "Enter label: " "" entered_label ; then
                                        if [ -z "${entered_label}" ] ; then
                                                continue
                                        fi
                                fi
                                # Execute label change with the suitable tool
                                case "$fstype" in 
                                        ext2|ext3|ext4) ${__SUDO__}tune2fs -L "${entered_label}" "${original_src}" ;;
                                        ntfs) _loadDep "ntfs-3g" ; ${__SUDO__}ntfslabel "${original_src}" "${entered_label}" ;;
                                        exfat) _loadDep "exfatlabel@exfatlabel|exfat-utils" ; ${__SUDO__}exfatlabel "${original_src}" "${entered_label}" ;;
                                        vfat) _loadDep "dosfstools" ; ${__SUDO__}fatlabel "${original_src}" "${entered_label}" ;;
                                        *) ;;
                                esac
                                if [ $? -eq 0 ] ; then
                                        Sumo__im_manageTimedErrorMessage false "You may have to refresh list with 'u' key if the new label does not become visible after the timeout" 2
                                else    
                                        Sumo__im_manageTimedErrorMessage true "Label assignement failed! " 2
                                        continue
                                fi
                                SUMO__VARS["CACHE_LIST_DATA_DB"]="" # Force rebuild of list
                        elif [ $originalIndex -eq 250 ] ; then
                                # Erase history item
                                if [ ${SUMO__CURRENT_SELECT_INDEX} -gt ${SUMO__CURRENT_LIST_SIZE} ] ; then
                                        Sumo__eraseHistoryItem "$src" true
                                        if [ $? -ne 0 ] ; then
                                                Sumo__im_manageTimedErrorMessage false "Item was not removed from history" 2
                                        fi
                                        continue
                                else
                                        continue
                                fi
                        elif [ $originalIndex -eq 251 ] ; then 
                                # Browser
                                if [ ! -z "$mntp" ] ; then
                                        if [ ! -d "$mntp" ]  ; then
                                                Sumo__im_manageTimedErrorMessage true "Folder '$mntp' does not exist." 2
                                                continue
                                        fi
                                        local browser=""
                                        if [ ! -z "${SUMO__VARS["BROWSER"]}" ] ; then
                                                browser="${SUMO__VARS["BROWSER"]}"
                                                if which "$browser" &> /dev/null; then
                                                        "$browser" "$mntp" &> /dev/null  &
                                                        continue
                                                fi
                                        fi                                        
                                        if which nautilius &> /dev/null ; then
                                                nautilus "$mntp" &> /dev/null  &
                                                continue
                                        elif  which dolphin &> /dev/null ; then
                                                dolphin "$mntp" &> /dev/null  &
                                                continue
                                        else
                                                _log_warn "No valid browser was found. Please configure one with 'browser' property in configuration file."
                                        fi
                                fi
                        elif [ $originalIndex -eq 245 ] ; then 
                                # Part function is not available in the recent list.
                                # Partitioning can not be triggered on an item of the history list.
                                # It must be a visible disk device in the main list
                                if [ ! -z "$recentdate" ]  ; then
                                        continue
                                fi

                                # Formatting must having been allowed according to the known information set up from awk script
                                if [ "${formatAllowed}" != "yes" ] ; then
                                        Sumo__im_resetBottomArea
                                        Sumo__im_manageTimedErrorMessage true "Partitioning is not allowed for '$original_src'. It must be a disk." 2
                                        continue
                                fi

                                Term__clear
                                #Sumo__im_resetBottomArea
                                local availPartTypes=""
                                Dev_getPartNamesReduced availPartTypes
                                availPartTypes="$(echo "$availPartTypes"|sort)"

                                Input__cursorSelect "${availPartTypes}" "${_pal['bg_blue']}Select partition type:${Term__reset_color}" 1
                                local key=$?
                                Term__restoreCursor
                                if [ $key -eq 0 ] ; then
                                        echo
                                        Sumo__im_manageTimedErrorMessage true "Aborted." 2
                                        continue
                                fi

                                #local availPartTypesAsArray=($availPartTypes) #local partTypeName="${availPartTypesAsArray[$(($key-1))]}"
                                local partTypeName="$(echo "${availPartTypes}"| head -n $key | tail -n1 )" # This enables to manage value containing spaces
                                Str__trimOnce "$partTypeName" partTypeName "'"

                                _log "Going to create a ${partTypeName} partition."

                                # Ensure any related mounts are unmounted.
                                if [ ! -z "$mntp" ] || [ "$hasMountedChild" = "yes" ] ; then
                                        Sumo__im_manageUnmount "${original_src}" "$src" "Disk formatting"
                                        operationResult=$?
                                        if [ $operationResult -ne 0 ] ; then
                                                continue
                                        fi
                                fi

                                Sumo__im_resetBottomArea
                                local partTypeUUID
                                Dev_getPartUUID "${partTypeName}" partTypeUUID
                                if [ -n "$partTypeUUID" ]  ; then
                                        echo "$0 --caller=$mypid -s --part-disk=${partTypeUUID} $original_src" >> "${__LOG_FILE__}"
                                        $0 ${ghostOpt} --caller="$mypid" -s --part-disk="${partTypeUUID}" "$original_src"

                                        operationResult=$?
                                        if [ $operationResult -eq 0 ] ; then
                                                Sumo__list_setup plain
                                                Sumo__im_adaptTermSize
                                                #Term__countdown "Finished. Continuing in " 3 " seconds" 
                                        fi
                                else
                                        _log_err "Internal error: UUID could not be retrieved for partition type '${partTypeName}'"
                                fi
                                operationResult=$?
                        elif [ $originalIndex -eq 246 ] ; then 
                                # Flashing function is not available in the recent list.
                                # Flashing can not be triggered on an item of the history list.
                                # It must be a visible disk device in the main list
                                if [ ! -z "$recentdate" ]  ; then
                                        continue
                                fi
                                # Flashing must having been allowed according to the known information set up from awk script
                                if [ "${formatAllowed}" != "yes" ] ; then
                                        Sumo__im_resetBottomArea
                                        Sumo__im_manageTimedErrorMessage true "Flashing is not allowed for '$original_src'. It must be a disk." 2
                                        continue
                                fi

                                # Ensure any related mounts are unmounted.
                                if [ ! -z "$mntp" ] || [ "$hasMountedChild" = "yes" ] ; then
                                        Sumo__im_manageUnmount "${original_src}" "$src" "Disk flashing"
                                        operationResult=$?
                                        if [ $operationResult -ne 0 ] ; then
                                                continue
                                        else
                                               Term__countdown "Continuing in " 2 " seconds" 
                                        fi
                                fi
                                Sumo__im_resetBottomArea                                
                                local enteredDiskFile=""
                                local downloadFolder="$HOME/Downloads"
                                if [ ! -z "${SUMO__VARS["ISO_DIRECTORY"]}" ] ; then
                                        downloadFolder="${SUMO__VARS["ISO_DIRECTORY"]}"
                                fi
                                local quest="Enter disk image file"
                                local default="Browse in '${downloadFolder}' folder" 
                                if [ ! -d "${downloadFolder}" ] ; then 
                                        _log_warn "Folder '${downloadFolder}' of ISO images does not exist!"
                                        downloadFolder="."
                                        default="Browse in '${downloadFolder}' folder"                                                 
                                fi
                                local imgType
                                local allFiles=""
                                local imgTypes=(${SUMO__VARS["ALLIMAGETYPES"]}) # ="luks img qcow2 iso vmdk vdi vera hc"
                                for imgType in "${imgTypes[@]}"; do
                                        local lsRes="$(ls -1 -d --file-type "${downloadFolder}/"*.${imgType} 2>/dev/null | grep -v -E '/$')"
                                        if [ ! -z "$lsRes" ] ; then
                                                if [ -z "$allFiles" ] ; then
                                                        allFiles="${lsRes[@]}"
                                                else
                                                        allFiles="${allFiles}
${lsRes[@]}"
                                                fi
                                        fi
                                done

                                if [ -z "$allFiles" ] ; then
                                        downloadFolder=""
                                        default="Abort"; 
                                fi

                                if Input__Word "$quest" "$default" enteredDiskFile "^([\.a-zA-Z0-9\ '/_-])*$" ; then
                                        if [ "${enteredDiskFile}" = "$default" ] ; then
                                                if [ ! -d "${downloadFolder}" ] ; then 
                                                        continue
                                                fi
                                                local maxListSize=$(( ${SUMO__VARS["nbMaxDetailsSectionLines"]} - 4 ))
                                                if [ $(echo "$allFiles"|wc -l) -gt $maxListSize ] ; then
                                                        Term__clear
                                                fi                                                
                                                Input__cursorSelect "${allFiles}" "${_pal['bg_blue']}Select disk file:${Term__reset_color}" 1
                                                local key=$?
                                                Term__restoreCursor
                                                if [ $key -eq 0 ] ; then
                                                        echo
                                                        Sumo__im_manageTimedErrorMessage true "Aborted." 2
                                                        continue
                                                else
                                                        local allFilesAsArray=($allFiles)
                                                        enteredDiskFile="$(echo "$allFiles"|head -n "$key"|tail -n1)"
                                                        #_log "enteredDiskFile : '$enteredDiskFile'"
                                                fi
                                        elif [ ! -f "${enteredDiskFile}" ] ; then
                                                echo
                                                Sumo__im_manageTimedErrorMessage true "'${enteredDiskFile}' does not exist. Incorrect path? Aborted."  2
                                                continue
                                        fi
                                fi

                                Sumo__im_resetBottomArea
                                $0 ${ghostOpt} --caller="$mypid" -s --flash-disk="$enteredDiskFile" "$original_src"
                                operationResult=$?
                                if [ $operationResult -eq 0 ] ; then
                                        Sumo__list_setup plain
                                        Sumo__im_adaptTermSize
                                        #Term__countdown "Finished. Continuing in " 3 " seconds" 
                                fi
                        elif [ $originalIndex -eq 247 ] ; then 
                                # Formatting function is not available in the recent list.
                                # Formatting can not be triggered on an item of the history list.
                                # It must be a visible disk device in the main list
                                if [ ! -z "$recentdate" ]  ; then
                                        continue
                                fi
                                # Formatting must having been allowed according to the known information set up from awk script
                                if [ "${formatAllowed}" != "yes" ] ; then
                                        Sumo__im_resetBottomArea
                                        Sumo__im_manageTimedErrorMessage true "Format is not allowed for '$original_src'. It must be a disk." 2
                                        continue
                                fi

                                Term__clear
                                #Sumo__im_resetBottomArea
                                local availFstypes=(${Dev__fstypes})
                                local wipeMenu="*Wipe off any file system*"
                                availFstypes+=("$wipeMenu")
                                local fsTypeSelection="${Dev__fstypes}
${wipeMenu}"
                                Input__cursorSelect "${fsTypeSelection}" "${_pal['bg_blue']}Select file system type or wipe off any existing fs:${Term__reset_color}" 1
                                local key=$?
                                Term__restoreCursor
                                if [ $key -eq 0 ] ; then
                                        echo
                                        Sumo__im_manageTimedErrorMessage true "Aborted." 1
                                        continue
                                fi
                                local selectedFs="${availFstypes[$(($key-1))]}"
                                if [ "$selectedFs" = "$wipeMenu" ] ; then
                                        _log "Going to wipe off any file systems on the disk."
                                        if Input__confirm "ALL DATA ARE GETTING LOST on ${original_src}. ARE YOU SURE?" ; then
                                                echo
                                                Dev__wipeDisk "${original_src}"
                                                operationResult=$?
                                        else
                                                echo
                                                Sumo__im_manageTimedErrorMessage true "Aborted." 1
                                                continue
                                        fi
                                else
                                        _log "Going to create a ${selectedFs} file system."
                                        # Ensure any related mounts are unmounted.
                                        if [ ! -z "$mntp" ] || [ "$hasMountedChild" = "yes" ] ; then
                                                Sumo__im_manageUnmount "${original_src}" "$src" "Disk formatting"
                                                operationResult=$?
                                                if [ $operationResult -ne 0 ] ; then
                                                        continue
                                                fi
                                        fi

                                        Sumo__im_resetBottomArea
                                        $0 ${ghostOpt} --caller="$mypid" -s -F -t "${selectedFs}" "$original_src"
                                        operationResult=$?
                                fi

                                if [ $operationResult -eq 0 ] ; then
                                        Term__countdown "Finished. Continuing in " 3 " seconds" 
                                        Sumo__list_setup plain
                                        Sumo__im_adaptTermSize
                                fi
                        #Sys__getPID mypid # Deactivated for performances reason at the moment , and actual ID not used
                        elif [ $notmountable -eq 0 ] ; then  
                                printf '\033[u'
                                continue
                        # Mountpoint is empty, this is an order to mount, except if there is a delegate device in charge of unmounting.
                        elif [ -z "$mntp" ] && [ "$hasMountedChild" != "yes" ] && [ $nolink -ne 0 ]; then
                                # FOR DEBUG
                                #_logf "->> Mountpoint is empty, this is an order to mount, except if there is a delegate device in charge of unmounting. hasMountedChild: ${hasMountedChild}, isNetworkLink:${isNetworkLink}, recentdate:${recentdate},  doRemount? '${doRemount}' nolink='${nolink}', statusMountStuck=${statusMountStuck}, link_detected set?? '${SUMO_DETAIL_HIDDEN_DATA_MAP["link_detected"]}'"
                                #exit -1 "Debug abort"

                                Sumo__im_stopMountMonitoring # timer stopped for avoid unnecessary update and flickering. It will be restarted from __cursor function
                                Sumo__im_resetBottomArea
                                # TODO CONFIRM: delegate are not relevant for the mounting 
                                #if $srcIsDelegate ; then src=${original_src} ; fi
                                $0 ${ghostOpt} --caller="$mypid" -s "$src"
                                operationResult=$?
                        # This is either a remount or an unmount order
                        else
                                # FOR DEBUG
                                #_logf "->> hasMountedChild: ${hasMountedChild}, isNetworkLink:${isNetworkLink}, recentdate:${recentdate},  doRemount? '${doRemount}' nolink='${nolink}', statusMountStuck=${statusMountStuck}, link_detected set?? '${SUMO_DETAIL_HIDDEN_DATA_MAP["link_detected"]}'"
                                #exit -1 "Debug abort"

                                Sumo__im_stopMountMonitoring # timer stopped for avoid unnecessary update and flickering. It will be restarted from __cursor function
                                Sumo__im_resetBottomArea

                                if [ $doRemount -ne 0 ] && [ "$hasMountedChild" == "yes" ] && [ -z "$isNetworkLink" ] && [ -z "$recentdate" ] && [ $nolink -ne 0 ] ; then
:<<'EOF'
                                        if [ -z "${delegate_device}" ] ; then
                                                if ! Input__confirm "Confirm unmounting '$src' and all its contained devices?" ; then
                                                        continue
                                                fi
                                                _log ""
                                        fi
EOF
                                        $0 ${ghostOpt} --caller="$mypid" -y -s -u -a "$src"
                                        operationResult=$?
                                        if [ $operationResult -eq 0 ] ; then
                                                _log_dbg "RESET SUMO__NOT_MOUNTED for $src"
                                                local recentKey=${src// /§} # Escape spaces when used as keys to enable proper saving
                                                SUMO__NOT_MOUNTED["$recentKey"]="${SUMO__CURRENT_ROW}"
                                                if Str__startsWith "$recentKey" "${Dev__mapperdir}" ; then
                                                        Sumo__eraseHistoryItem "$recentKey" false
                                                fi   
                                        fi
                                elif [ $doRemount -eq 0 ] && [ $nolink -ne 0 ] ; then
                                        #FOR DEBUG
                                        #_logf "Remount initiated. src='$src', mntp='$mntp', embeddingdiskfilePath='${embeddingdiskfilePath}', srcIsDelegate=${srcIsDelegate}, original_src=${original_src}"

                                        if [ -z "$recentdate" ]  ; then
                                                # unmount first
                                                $0 ${ghostOpt} --caller="$mypid" -y -s -u "$mntp"
                                                operationResult=$?                                                
                                                if [ $operationResult -eq 0 ] ; then
                                                        # TODO CONFIRM: delegate are not relevant for the mounting 

                                                        #DEBUG
                                                        #if $srcIsDelegate ; then src=${original_src} ; fi
                                                        #_exit -1 "UNMOUNT of OK!!!!!!!!!!!!"

                                                        # remount
                                                        if [ ! -z "$embeddingdiskfilePath" ] ; then
                                                                src="$embeddingdiskfilePath"
                                                        fi
                                                        if [ $ro -eq 0 ] ; then
                                                                $0 ${ghostOpt} --caller="$mypid" -s -y "$src" "$mntp" # ro to rw
                                                        else
                                                                $0 ${ghostOpt} --caller="$mypid" -s -y "$src" "$mntp" -o ro # rw to to
                                                        fi
                                                        operationResult=$?
                                                        if [ $operationResult -eq 0 ] ; then
                                                                # Read-only flag is not part of the source list setup with lsblk and findmnt
                                                                # It is retrieved from the filter awk file from findmnt
                                                                # If cache is not cleared, then the ro flag may not appear!
                                                                SUMO__VARS["CACHE_LIST_DATA_DB"]="" # Force rebuild of list
                                                        fi
                                                #else
                                                #FOR DEBUG
                                                #        _exit -1 "UNMOUNT of REMOUNTED FAILED" # DEBUG
                                                fi
                                        else # No direct rw/ro remount for recent item
                                                #FOR DEBUG
                                                #_exit -1 "No direct rw/ro remount for recent item !!! !"

                                                continue
                                        fi
                                else # unmount order or mounting of a recent
                                        #FOR DEBUG
                                        #_logf "initiated unmount or recent remount. src='$src', mntp='$mntp', embeddingdiskfilePath='${embeddingdiskfilePath}', srcIsDelegate=${srcIsDelegate}, original_src=${original_src}"
                                        if [ ! -z "$recentdate" ]  ; then

                                                local parent_mntp="${SUMO_DETAIL_HIDDEN_DATA_MAP["/parentmountpoint"]}"
                                                local parent_src="${SUMO_DETAIL_HIDDEN_DATA_MAP["/parentmountsource"]}"
                                                local doTryMountEmbedding=1
                                                # If parent is not known (either mounted or not), look for the embedding disk file path
                                                # property
                                                if [ ! -z "${parent_src}" ] ; then
                                                        local recentKey=${parent_src// /§} # Escape spaces when used as keys to enable proper saving                                                
                                                        if [ -z "${SUMO__RECENT["${recentKey}"]}" ] ; then
                                                                _log_dbg "Remounting recent: No historic info available on parent '${parent_src}]}' found for $src"
                                                                doTryMountEmbedding=0
                                                        elif [ ! -z "$embeddingdiskfilePath" ] ; then
                                                                local actualParentSrc
                                                                Sumo__getRecentIndirection "${parent_src}" actualParentSrc
                                                                _log_dbg "testing if $embeddingdiskfilePath is mounted, actual parent is $actualParentSrc ..."                                                                
                                                                local recentKey=${actualParentSrc// /§} # Escape spaces when used as keys to enable proper saving
                                                                if [ ${#SUMO__NOT_MOUNTED["$recentKey"]} -ne 0 ] ; then # not mounted!
                                                                         _logf "Parent must be mounted: $actualParentSrc ..."
                                                                        doTryMountEmbedding=0
                                                                fi
                                                        fi
                                                else    
                                                        doTryMountEmbedding=0
                                                fi

                                                if [ $doTryMountEmbedding -eq 0 ] ; then
                                                        if [ ! -z "$embeddingdiskfilePath" ] ; then
                                                                _logf "Remounting recent: found embedding disk $embeddingdiskfilePath"
                                                                parent_src="$embeddingdiskfilePath"
                                                                Str__trimOnce "${parent_src}" parent_src "\"" 
                                                                local embedCoreFilename
                                                                File__corename "${embeddingdiskfilePath}" embedCoreFilename
                                                                parent_mntp="$embedCoreFilename"

                                                                Sumo__getRecentIndirection "${parent_src}" parent_src
                                                        fi
                                                fi
                                                Str__trimOnce "${parent_src}" parent_src "\""

                                                local mountByLabel=false
                                                #_log_dbg "REMOUNT RECENT"
                                                #_log_vars parent_src formatAllowed devLabel
                                                if [ ! -z "${devLabel}" ]  ; then
                                                        local actualDevLabel
                                                        if Dev__getBlockDeviceLabel "$src" actualDevLabel ; then
                                                                 _log_dbg "REMOUNT RECENT LABEL CHECK: actual block label='${actualDevLabel}', recent label:'$devLabel'"
                                                                if [ "$devLabel" != "${actualDevLabel}" ] ; then
                                                                        _log_warn "The label '${actualDevLabel}' of device '$src' doesn't match the label '$devLabel' recorded for that device in history."
                                                                        _log_warn "The device '$src' may not be the correct device you're willing to mount."
                                                                        Input__confirm "Try to mount the device labelled '$devLabel' instead or continue mounting device '$src'?"
                                                                        if [ $? -eq 0 ] ; then mountByLabel=true; fi
                                                                fi
                                                        fi
                                                fi

                                                # TODO CONFIRM: delegate are not relevant for the mounting 
                                                if $srcIsDelegate ; then src=${original_src} ; fi

                                                if $mountByLabel ; then
                                                        _log_dbg "REMOUNT RECENT MOUNT BY LABEL ${devLabel} instead of $src of label ${actualDevLabel}"
                                                        local roOpt=""
                                                        if [ $ro -eq 0 ] ; then roOpt="-o ro"; fi
                                                        $0 ${ghostOpt} --caller="0" -s -y -L "${devLabel}" "$mntp" "${roOpt}"
                                                        # Upon success remove the ancient invalid history entry with invalid src
                                                        if [ $? -eq 0 ] ; then
                                                                Sumo__eraseHistoryItem "$src" true
                                                        fi
                                                else
                                                        Sumo__remountRecent "$src" "$mntp" "$ro" 0 "${parent_src}" "${parent_mntp}"
                                                fi
                                                operationResult=$?                                                
                                        else                                        
                                                if [ $nolink -eq 0 ] ; then
                                                        local lazyumount
                                                        _log "Connection is stuck. It should preferably be reestablished to prevent data loss."
                                                        _log "Please, check first host and link status if necessary ((cable?)."
                                                        Input__confirm "Continue with lazy unmount (this may yet take some time to complete)?"
                                                        lazyumount=$?
                                                        _log ""
                                                        if [ $lazyumount -eq 0 ] ; then
                                                                if [ ! -z "$mntp" ] ; then
                                                                        $0 ${ghostOpt} --caller="$mypid" -y -s -u --lazy "$mntp" #--debug-mode
                                                                else
                                                                        $0 ${ghostOpt} --caller="$mypid" -y -s -u --lazy "$src" #--debug-mode
                                                                fi
                                                                operationResult=$?                                                
                                                                #_log_dbg "After call to unmount lazy"
                                                        fi
                                                else
                                                        $0 ${ghostOpt} --caller="$mypid" -y -s -u  "$mntp"
                                                        operationResult=$?                                                
                                                fi

                                                if [ $operationResult -eq 0 ] ; then
                                                        _log_dbg "RESET SUMO__NOT_MOUNTED for $src"
                                                        # Do this, because some items like disk files disappear fully from the list
                                                        # when unmount, whereby SUMO__NOT_MOUNTED won't be reset from saveRecentList
                                                        #Str__trim "$src" src "\"" # Key is without quotes always
                                                        local recentKey=${src// /§} # Escape spaces when used as keys to enable proper saving
                                                        SUMO__NOT_MOUNTED["$recentKey"]="${SUMO__CURRENT_ROW}"
                                                        if Str__startsWith "$recentKey" "${Dev__mapperdir}" ; then
                                                                Sumo__eraseHistoryItem "$recentKey" false
                                                        fi   

                                                else
                                                        Sumo__im_manageTimedErrorMessage true "Unmount failed. Please check log '$_errlog' file for details." 3
                                                        continue
                                                fi
                                        fi
                                fi
                        fi
                        if [ $operationResult -ne 0 ] ; then
                                Sumo__im_manageTimedErrorMessage true "Please check log '$_errlog' file for details." 4
                        fi
                        printf '\033[u' 
                        #tput cup 0 0
                        #Sumo__list plain
                        Sumo__list_setup plain
                        Sumo__im_adaptTermSize                        
                fi
        else
                printf '\n'
                #_exit 0 "" # Do perform the cleanup
                _quit ""
                break
        fi

        done
}

Sumo__getRecentIndirection()
{
        local key="$1"
        local -n out_indirKey=$2
        local fullpath="$(realpath -m "$key")"
        #_log_dbg "true full path='$fullpath'"
        if [ ${#SUMO__RECENT_KEY_INDIRECTION["${fullpath}"]} -gt 0 ]  ; then
                #_log_dbg "FOUND INDIRECTION full path='$fullpath'"
                out_indirKey="$fullpath"
        else
                out_indirKey="$key"
        fi      
}

:<<'EOF'
This function is used to remount a device from the history, ensuring recursive remounting of required parent devices.
@param [1] source device
@param [2] mountpoint
@param [3] readonly flag
@param [4] recursion level
@param [5] parent source device
@param [6] parent mountpoint
EOF

Sumo__remountRecent()
{
        _log_dbg "Sumo__remountRecent '$1' '$2' '$3' '$4' '$5' '$6'"

        local src="$1"
        local mntp="$2"
        local ro="$3"
        local reclevel=$4
        local parent_src="$5"
        local parent_mntp="$6"
        local remountResult=0

        local ghostOpt=""
        if ${SUMO__VARS["HISTORY_GHOST"]} ; then ghostOpt="--ghost" ; fi

        if [ ! -z "${parent_src}" ] && [ ! -z "${parent_mntp}" ] ; then
                local recentKey=${parent_src// /§} # Escape spaces when used as keys to enable proper saving        
                if [ ! -z "${SUMO__RECENT["${recentKey}"]}" ] ; then
                        declare -A hiddenDataMap
                        declare -A ranksDataMap
                        Sumo__list_decodeHiddenData "${SUMO__RECENT["${recentKey}"]}" hiddenDataMap ranksDataMap
                        
                        # The parent src may have been redefined with a disk file by caller. Refresh mntp with actual mountpoint of this parent
                        # Moreover, we should always use the realpath if available
                        parent_mntp="${hiddenDataMap["mountpoint"]}" 
                        if [ ! -z "${hiddenDataMap["mountpoint_realpath"]}" ] ; then
                                parent_mntp="${hiddenDataMap["mountpoint_realpath"]}"
                        fi

                        local grand_parent_mntp="${hiddenDataMap["/parentmountpoint"]}"
                        local grand_parent_src="${hiddenDataMap["/parentmountsource"]}"
                        local parent_recentdate="${hiddenDataMap["/recent"]}"
                        # If /recent is defined, it means the parent may in the history and is therefore not mounted
                        _log_dbg "Sumo__remountRecent relvel=$reclevel recent of parent '${parent_recentdate}', RECENT: ${SUMO__RECENT["${recentKey}"]} "
                        if [ ! -z "${parent_recentdate}" ] ; then

                                if [ $reclevel -eq 0 ] ; then
                                        if [ ! -z "${parent_src}" ] ; then
                                                Input__confirm  "Mounting of '$src' on '$mntp' requires mounting of the parent source '${parent_src}' on '${parent_mntp}'. Continue?"
                                                if [ $? -ne 0 ] ; then 
                                                        return 1
                                                fi
                                                _log ""
                                        fi
                                fi

                                Sumo__remountRecent "${parent_src}" "${parent_mntp}" 1 $(($reclevel + 1)) "${grand_parent_src}" "${grand_parent_mntp}"
                                remountResult=$?

                                # When remounting the containing disk file and current source is not itself a disk file
                                # It is not worth mounting the initial device, since all 
                                # partition inside are expected to be mounted 
                                if [ $reclevel -eq 0 ] && [ -f ${parent_src} ] && [ ! -f "$src" ]; then
                                        return 0
                                fi
                                if [ ${remountResult} -ne 0 ] ; then
                                        return ${remountResult}
                                fi
                        fi
                else
                        _log_warn "Attempting to remount '$src' on '$mntp', but no historic record available for parent '${parent_src}'. Mounting may fail without explicitly remounting parent beforehand."
                fi
        fi

        if [ -z "$mntp" ] ; then
                _log_err "Mountpoint for recent '$src' is not known."
                return 1
        fi
:<<'EOF'
        if [ -z "$mntp" ] ; then
                local fileCorename
                File__corename "${src}" fileCorename
                local defaultMountpoint
                defaultMountpoint="$(dirname "${src")/${fileCorename}"
                if ! Input__dirpath "Enter the target mount " "${themountpoint}" 1 themountpoint ; then
                        _exit -1 "Aborted."
                fi

                local savedImgFile="${SUMO__VARS["IMG_FILE"]}"
                SUMO__VARS["IMG_FILE"]="$savedImgFile"
                Sumo__manageValidMountpointSetting Sumo__getMountpoint "$(realpath -m "$defaultMountpoint")"  
        fi
EOF

        _log "Mounting of '$src' on '$mntp'..."
        #sleep 60
        local debugMode=""
        if [ "${__LOG_DEBUG__}" = "0" ] ; then debugMode="--debug-mode" ;  fi

        if Str__startsWith "$src" 'curlftpfs#' ; then
                Str__toTail src 'curlftpfs#'
        fi
        #_log "Sumo__remountRecent '$src'"

        local cmd="$0 ${ghostOpt} --caller='0' "${debugMode}" -s -y '$src' '$mntp'"
        if [ $ro -eq 0 ] ; then
                cmd="${cmd} -o ro"
        fi
        _logf "Executing command: ${cmd}"
        eval "${cmd}"
        remountResult=$?
        #SUMO__CURRENT_SELECT_INDEX=1
        _log_dbg "END remountRecent"
        return ${remountResult}
} 

:<<'EOF'
This is called at start of main() to mark all read recent items as "not mounted".
EOF

Sumo__resetNotMountStatus()
{
        local key
        local val
        local firstVal=0
        
        for key in "${!SUMO__RECENT_IGNORED[@]}"
        do
                SUMO__RECENT_IGNORED["$key"]=""
        done

        for key in "${!SUMO__RECENT[@]}"
        do
                # Consider by default as not mounted
                SUMO__NOT_MOUNTED["$key"]="${SUMO__RECENT["$key"]}"
        done
}

:<<'EOF'
Adjusts first col width so as to be at minimum as long
the value specified as argument
@param [1] min. col width required.
EOF

# This may be removed one day , Sumo__adjustColumnWidth is used
Sumo__adjustFirstColumnWidth()
{
        local minWidthRequired=$1
        local currentColsWidthAsArray=(${SUMO__COLS_WIDTH})
        local cur1stColWidth=${currentColsWidthAsArray[0]}
        if [ ${minWidthRequired} -gt $cur1stColWidth ] ; then
                SUMO__COLS_WIDTH="${minWidthRequired} ${currentColsWidthAsArray[@]:1}"
                #_log_dbg "Sumo__adjustFirstColumnWidth NEW 1ST COLUMN WIDTH : '${SUMO__COLS_WIDTH}'"
        fi
}

:<<'EOF'
Adjusts the width of column of rank given by 1st argument (from 0)
so as to be at minimum as long the value specified as 2nd argument
@param [1] column rank
@param [2] min. col width required.
@param [3] output add number of columns or 0 if none
EOF

Sumo__adjustColumnWidth()
{
        local colIndex=$1
        local minWidthRequired=$2
        local -n __out__addedCols=$3
        __out__addedCols=0
        local currentColsWidthAsArray=(${SUMO__COLS_WIDTH})
        local curColWidth=${currentColsWidthAsArray[$colIndex]}
	#echo "====> Sumo__adjustColumnWidth : colIndex=$colIndex ${SUMO__COLS_WIDTH}), minWidthRequired:$minWidthRequired, curColWidth:$curColWidth">> dbg.txt
        if [ ${minWidthRequired} -gt $curColWidth ] ; then
                __out__addedCols=$(( $minWidthRequired - $curColWidth  ))
                if [ $colIndex -eq 0 ] ; then
                        SUMO__COLS_WIDTH="${minWidthRequired} ${currentColsWidthAsArray[@]:1}"
                        #echo "====> Sumo__adjustColumnWidth : colIndex=$colIndex NEW! ${SUMO__COLS_WIDTH}), minWidthRequired:$minWidthRequired, curColWidth:$curColWidth">> dbg.txt
                else
                        local afterColIndex=$(($colIndex+1))
                        SUMO__COLS_WIDTH="${currentColsWidthAsArray[@]:0:${colIndex}} ${minWidthRequired} ${currentColsWidthAsArray[@]:${afterColIndex}}"
                        #echo "====> Sumo__adjustColumnWidth : colIndex=$colIndex NEW! ${SUMO__COLS_WIDTH}), minWidthRequired:$minWidthRequired, curColWidth:$curColWidth">> dbg.txt
                fi
                #_log_dbg "Sumo__adjustFirstColumnWidth NEW 1ST COLUMN WIDTH : '${SUMO__COLS_WIDTH}'"
        fi
}

:<<'EOF'
Updates the maximum column widths list (SUMO__COLS_WIDTH) according to the entry of the history passed as first argument.
At the end, it also updates SUMO__LIST_LINE_WIDTH.
@param [1] history line of recent mount/unmount
EOF

Sumo__adjustMetricsFromRecent()
{
        local line="$1"    
        local recentKey="$2"    
        local originalKeyValue="$3"
        declare -A lineMetrics

        Sumo__list_decodeHiddenMetrics "${line}" lineMetrics
      
        local currentColsWAsArray=(${SUMO__COLS_WIDTH})

        #_log_dbg "Sumo__adjustMetricsFromRecent '${lineMetrics["line_width"]}' '${lineMetrics["nb_cols"]}' '${#currentColsWAsArray[@]}' , for line '$line'"

        if ! Int__isInt ${lineMetrics["nb_cols"]} ; then
                _log_warn "This is possible an erroneous line in the recent list file due to nb_cols= '${lineMetrics["nb_cols"]}'  , concerning device named '$recentKey' associated with the data '$originalKeyValue', which is not recognized. Ignored."
                return 1
        fi

        if [ ${lineMetrics["nb_cols"]} -ne ${#currentColsWAsArray[@]}  ] ; then
                _log_err "mismatch of number of columns between recent list and current list."
                _log_err "Please cleanup the recent list file. Ignored."
                return 1                
        fi        

        local newColsWidth=""
        local colIndex=0
        local newLineWidth=0
        while [ $colIndex -lt ${#currentColsWAsArray[@]} ]
        do
                local greatestColWidth=0
                Int__max ${lineMetrics["$colIndex"]} ${currentColsWAsArray[$colIndex]} greatestColWidth
                newColsWidth="$newColsWidth $greatestColWidth"
                newLineWidth=$(($newLineWidth + $greatestColWidth + 1 ))
                colIndex=$(($colIndex + 1))
        done
        Str__trimOnce "$newColsWidth" newColsWidth
        SUMO__COLS_WIDTH="$newColsWidth"
        SUMO__LIST_LINE_WIDTH=$newLineWidth

        #_log_dbg "Sumo__adjustMetricsFromRecent new line width: $SUMO__LIST_LINE_WIDTH, new cols width : $newColsWidth"

        return 0
}

Sumo__adjustMetricsFromAdditionalNbCols()
{
        local addcols=$1
        #SUMO__COLS_WIDTH="$(( ${SUMO__COLS_WIDTH} + $addcols ))"
        SUMO__LIST_LINE_WIDTH="$(( ${SUMO__LIST_LINE_WIDTH} + $addcols ))"
}

:<<'EOF'
From the map SUMO__RECENT[] as set up by saveRecentList(), this function expands the current list with 
the history of recently used mounts. Items of the map are not already mounted, or not mounted anymore
(see SUMO__NOT_MOUNTED) are marked with "/recent" for being handled specifically via the menu.

This max widths of each column (SUMO__COLS_WIDTH) and max lines (SUMO__LIST_LINE_WIDTH)
are updated to consider those items of the recent list.
EOF

Sumo__completeListWithHistory()
{
        if [ "${SUMO__CURRENT_OPERATION}" = "list" ] &&  [ -z "${SUMO__VARS["INTERACTIVE"]}" ]; then
                return 1
        fi

        if [ ${SUMO__VARS["SHOW_HISTORY"]} -ne 0 ] ; then
                return 1
        fi

        SUMO__CURRENT_RECENTLIST_SIZE=0

        # Complete the list
        local key
        local val
        local initialVal
        local firstVal=0
        declare -A historyListMap
        local historyListMapDates=""
        for key in "${!SUMO__RECENT[@]}"
        do
                #_log_dbg "key '$key' value '${SUMO__RECENT["$key"]}'"
                #_log_dbg "not mnt: '${SUMO__NOT_MOUNTED["$key"]}' "

                if [ ! -z "${SUMO__RECENT_IGNORED["$key"]}" ] ; then
                        # Filtered items shall not appear in history either
                        # _log_dbg "Sumo__completeListWithHistory: marked as ignored: '$key' ->'${SUMO__RECENT_IGNORED["$key"]}'"
                        continue
                elif [ ${#SUMO__NOT_MOUNTED["$key"]} -eq 0 ] ; then 
                        # Actual mounted devices shall not appear in the history
                        # _log_dbg "Sumo__completeListWithHistory: marked as mounted!: '$key' ->'${SUMO__RECENT_IGNORED["$key"]}'"
                        continue 
                else
                        # If the source is not marked as mounted, add it
                        #_log_dbg "Sumo__completeListWithHistory in history: '$key'"

                        initialVal="${SUMO__RECENT["$key"]}"
                        val="${initialVal}"

                        # It can happen that items in recent history are erase e.g. see below SUMO__RECENT["$key"]=""
                        # In that case empty values shall be detected and ignored
                        if [ -z "${val}" ] ; then
                                continue
                        fi
                        #_log "completeHistory : key:'$key' val:'${val}'" >> debug.txt # DEBUG

                        declare -A hiddenDataMap
                        declare -A ranksDataMap
                        Sumo__list_decodeHiddenData "${val}" hiddenDataMap ranksDataMap

                        local src="${hiddenDataMap["/mountsource"]}"
                        local delegate_mntp="${hiddenDataMap["/delegate-mountpoint"]}"
                        local mntp_realpath="${hiddenDataMap["mountpoint_realpath"]}"

                        local mntp="${hiddenDataMap["mountpoint"]}"
                        local formatAllowed="${hiddenDataMap["format"]}" # This indicates it is a physical disk
                        if [ "$mntp" == "-" ] ; then mntp="" ; fi

                        # Source mapping devices shall not appear in the history, rather the parent device mapped by the mapper
                        if Str__startsWith "$src" "${Dev__mapperdir}" && ! Str__contains "$val" "full§disk§file§path"; then
                                SUMO__RECENT["$src"]=""
                                unset SUMO__RECENT["$src"]
                                continue
                        fi

                        # Physical disk containing partitions should not appear in the history, it is anyway
                        # visible in the top list
                        if [ "${formatAllowed}" = "yes" ] && [ -z "${mntp}" ] ; then
                                continue
                        fi

                        # if there is a delegate mountpoint, it shall appear as the mount point in the history
                        if [ ! -z "${delegate_mntp}" ] ; then
                                local newMountPoint=${delegate_mntp// /§}
                                #Str__replace val "mountpoint:-" "mountpoint:${newMountPoint}" 
                                #Str__replace val "mountpoint: -" "mountpoint:${newMountPoint}"
                                # Replace the value 
                                Str__replace val "§ |" "${newMountPoint} |" 
                                #echo "REPLACE delegate_mntp replaced with '$newMountPoint'. News val : '$val'"
                        fi


                        # _log_dbg "Sumo__completeListWithHistory: marked for history mounted!: '$key' ->'${SUMO__RECENT_IGNORED["$key"]}'"

                        # do not put in history, items which are part of an embedding disk
                        if Str__contains "$val" "embedding§disk§file§path" && ! Str__contains "$val" "full§disk§file§path" ; then
                                 #_log_dbg "IGNORED do not put in history $key "
                                SUMO__RECENT["$key"]=""
                                unset SUMO__RECENT["$key"]
                                continue
                        fi
                        Str__trimOnce "$val" val 

                        #_log_dbg "Sumo__completeListWithHistory adding '$key' val='$val'"
                        #echo "Sumo__completeListWithHistory adding '$key' val='$val'" >> dbg.txt # DEBUG
                        val="$val|/recent:yes" # $(date +%s)"     # This field is only useful for handling the key commands in interactive mode
                        if ! Str__contains "${SUMO__RECENT["$key"]}" "/recent:yes" ; then
                                SUMO__RECENT["$key"]="$val"
                        fi

                        #local initialList="${SUMO__CURRENT_LIST}"
                        local historyRawLine=${val#*§§}
                        local historyDate="${historyRawLine%% *}"
                        local historyDateOrig="${historyDate}"
                        local historyCnt=0
                        # Handle equal dates by adding a counter
                        while [ ! -z "${historyListMap["$historyDate"]}" ] ; do
                                historyDate="${historyDateOrig}-$historyCnt"
                                historyCnt=$(($historyCnt+1))
                        done
                        historyListMap["$historyDate"]="$val"
                        historyListMapDates="$historyDate
$historyListMapDates"
                        SUMO__CURRENT_RECENTLIST_SIZE=$((${SUMO__CURRENT_RECENTLIST_SIZE}+1))

                        # Adjust the col width of the mountpoint. Because in case of delegate point like vmdisk,
                        # the parent enttry corresponding to nbd0 (and not nbd01 of the partition) is used for history
                        # But no mountpoint is displayed to this latter. When afterwards, the history is show, it shows 
                        # the delegate mount point whereas the space reserved for its display is that of the parent (empty)
                        local allButHeader=${initialVal#*§§} # All line but formatting
                        local displayLineOnly="${allButHeader% *}"  # Line without hidden data column (last field)
                        local displayedMountpoint=${displayLineOnly##* } 
                        local minDisplayMountPointWidth=${#displayedMountpoint}
                        Int__max ${#displayedMountpoint} ${#delegate_mntp} minDisplayMountPointWidth
                        #echo "====> displayedMountpoint '$displayedMountpoint' '${delegate_mntp}' minDisplayMountPointWidth:$minDisplayMountPointWidth" >> dbg.txt

                        local recentNbAddCols=0
                        Sumo__adjustColumnWidth 8 ${minDisplayMountPointWidth} recentNbAddCols

                        # Adjust metrics
                        if ! Sumo__adjustMetricsFromRecent "$val" "$key" "$initialVal" ; then
                                #SUMO__CURRENT_LIST="${initialList}"
                                SUMO__RECENT["$key"]=""
                                unset SUMO__RECENT["$key"]
                        fi
                fi
        done

        # Add the history items sorting them by date
        local historyDate=""
        local historyList=""
        while IFS= read -r historyDate
        do 
                if [ -z "$historyDate" ] ; then continue ; fi
                #_log "'$historyDate'"
                historyList="${historyList}
${historyListMap["$historyDate"]}"
        done < <(echo "$historyListMapDates"|sort -r)

        if [ ! -z "$historyListMapDates" ] ; then
                SUMO__CURRENT_LIST="${SUMO__CURRENT_LIST}
\\\\History " # last space is important to simulate hidden data column still expected elsewhere in the code
        else
                SUMO__CURRENT_LIST="${SUMO__CURRENT_LIST}
\\\\§ "        
        fi

        SUMO__CURRENT_LIST="${SUMO__CURRENT_LIST}${historyList}"

        # If history becomes empty, resize all metrics to those of the initial source list
        if [ ${SUMO__CURRENT_RECENTLIST_SIZE} -eq 0 ] ; then
                SUMO__LIST_LINE_WIDTH=${SUMO__LIST_LINE_WIDTH_WITHOUT_RECENT}
                SUMO__COLS_WIDTH="${SUMO__COLS_WIDTH_WITHOUT_RECENT}"
        else
                # If there is an history, first col is always at minimum
                # if the date format (see "$(date +"%F§%R")" + 1 space i.e 16)
                # 'YYY-MM-DD HH:MM ''
                local recentNbAddCols=0
                Sumo__adjustColumnWidth 0 16 recentNbAddCols
                Sumo__adjustMetricsFromAdditionalNbCols $recentNbAddCols
        fi
}

:<<'EOF'

From SUMO__CURRENT_LIST_WITHOUT_RECENT, this function  sets up the list of the recently mounted device,
as they will be stored in recentlist.yml. A stored record is a line of a mounted device (as it is displayed), 
where label field is used to store the latest date that the device was known as mounted. 
In memory, the record is stored in map SUMO__RECENT["$src"]. This field is only set when the device is known as mounted,
whereby it enables to keep track of the past target mount point once the device is unmounted afterwards.

This function is called each time the shown list is reconstructed/updated.

SUMO__CURRENT_LIST_SIZE is also set by this function.

SUMO__COLS_WIDTH is updated with regard to first column, since it is used to display the last use date instead
of label.
EOF

Sumo__setupRecentList()
{
        local originalLine=""
        local SUMO__CURRENT_LIST_WITHOUT_RECENT_CLEANED=""
        SUMO__CURRENT_LIST_SIZE=0
        SUMO__CURRENT_LIST_SIZE_WITHOUT_RECENT=0

        while IFS= read -r originalLine
        do 
                _log_dbg "SUMO__LIST_LINE_WIDTH: $SUMO__LIST_LINE_WIDTH $SUMO__COLS_WIDTH Sumo__setupRecentList: read line '$originalLine'"

                Sumo__list_decodeHiddenData "${originalLine}" SUMO_DETAIL_HIDDEN_DATA_MAP SUMO_DETAIL_RANKS_DATA_MAP
                #Sumo__list_decodeHiddenData "/ignore value: '${SUMO_DETAIL_HIDDEN_DATA_MAP["/ignore"]}'"
                if [ ! -z "${SUMO_DETAIL_HIDDEN_DATA_MAP["/ignore"]}" ] ; then
                        #_log_dbg "Sumo__setupRecentList: marked as ignore: '${SUMO_DETAIL_HIDDEN_DATA_MAP["/ignore"]}' ${SUMO__RECENT["${SUMO_DETAIL_HIDDEN_DATA_MAP["/ignore"]}"]}"
                        SUMO__RECENT_IGNORED["${SUMO_DETAIL_HIDDEN_DATA_MAP["/ignore"]}"]="yes"
                        continue
                fi

                if [ -z "${SUMO__CURRENT_LIST_WITHOUT_RECENT_CLEANED}" ] ; then
                        SUMO__CURRENT_LIST_WITHOUT_RECENT_CLEANED="${originalLine}"
                else
                        SUMO__CURRENT_LIST_WITHOUT_RECENT_CLEANED="${SUMO__CURRENT_LIST_WITHOUT_RECENT_CLEANED}
${originalLine}"
                fi

                #local isroot="${SUMO_DETAIL_HIDDEN_DATA_MAP["is root"]}" 
                local mntp="${SUMO_DETAIL_HIDDEN_DATA_MAP["mountpoint"]}"
                local src="${SUMO_DETAIL_HIDDEN_DATA_MAP["/mountsource"]}"
                local original_parent_src="${SUMO_DETAIL_HIDDEN_DATA_MAP["/parentmountsource"]}"
                local original_src="$src"
                local status="${SUMO_DETAIL_HIDDEN_DATA_MAP["status"]}"
                local diskfilePath="${SUMO_DETAIL_HIDDEN_DATA_MAP["full disk file path"]}" 
                local embeddingdiskfilePath="${SUMO_DETAIL_HIDDEN_DATA_MAP["embedding disk file path"]}" 
                local hasMountedChild="${SUMO_DETAIL_HIDDEN_DATA_MAP["/has-mounted-child"]}"
                local mountOpt="${SUMO_DETAIL_HIDDEN_DATA_MAP["mount options"]}"
                local realSource="${SUMO_DETAIL_HIDDEN_DATA_MAP["/real source"]}"

                local parent_src="${original_parent_src}"

                # The mount status will be set by the mounted childs
                #if [ ! -z "$isroot" ] ; then
                #        continue
                #fi
                
                if [ ! -z "${diskfilePath}" ] ; then 
                        src="${diskfilePath}" 
                        Str__trimOnce "$src" src "\""
                fi
                if [ ! -z "${realSource}" ] ; then 
                        src="${realSource}"
                fi

                #_log_dbg " ================>>> src? $src"

                if [ "$mntp" == "-" ] ; then mntp="" ; fi

                local recentKey=""

                if Str__startsWith "$original_src" 'curlftpfs#' ; then
                        recentKey="$original_src"
                        Str__toTail recentKey 'curlftpfs#'
                elif Net__isCloudDevice "${original_src}" ; then
                        # NOTE THIS IS ALREADY STORED IN 'real source'
                        # which is not exploited here. But it is 
                        # in updateSavedRecentList!
                        local _cloudURL
                        Net__getCloudURLFromDevice "${original_src}" recentKey 
                        recentKey=${recentKey// /§} # Escape spaces when used as keys to enable proper saving
                elif Str__contains "$mountOpt" "clientaddr=" && Net__isNFS "${original_src}" ; then
                        recentKey="nfs://${src}"
                        recentKey=${recentKey// /§} # Escape spaces when used as keys to enable proper saving
                elif Str__contains "$mountOpt" "upperdir=" ; then
                        Sumo__overlay_buildLogicalMountSourceFromMountOptions "$mountOpt" recentKey true
                else
                        recentKey=${src// /§} # Escape spaces when used as keys to enable proper saving
                fi
                _log_dbg "setup recent list : recentKey='$recentKey' '$src' '$mntp' '$mountOpt' '$originalLine'"
                #echo "setup recent list : recentKey='$recentKey' '$src' '$mntp' '$mountOpt' '$originalLine'" >> "dbg.txt"

                local recentKeyOriginalSrc=${original_src// /§} # Escape spaces when used as keys to enable proper saving
                local recentKeyParentSrc=${parent_src// /§} # Escape spaces when used as keys to enable proper saving
                local recentKeyEmbeddedFilePath=${embeddingdiskfilePath// /§} # Escape spaces when used as keys to enable proper saving
                if [ ! -z "$mntp" ] ||  [ "$hasMountedChild" == "yes" ] ; then
                        local newLine=""
                        local recentDate=""

                        # This does not modify the actual original line for display
                        # but rather returns a new line where label is replaced with date
                        # This new line is then put in SUMO__RECENT for internal management
                        # after the display of the original list and achieving operations.
                        Sumo__setDateOfRecentLine "$originalLine" newLine recentDate

                        # Adjust first col width to be at minimum as long
                        # as required to display the date
                        #
                        # NO: This corrupts the display! This modifies unduly
                        # COLS_WIDTH with label size of 16, which is then not inline
                        # with LINE_WIDTH, because the date is not shown for mounted items
                        # Once in history,the width will be adapted automatically
                        #Sumo__adjustFirstColumnWidth ${#recentDate}

                        SUMO__RECENT["$recentKey"]="$newLine"

                        SUMO__NOT_MOUNTED["$recentKey"]=""
                        SUMO__NOT_MOUNTED["${recentKeyOriginalSrc}"]=""
                        if [ ! -z "$embeddingdiskfilePath" ] ; then SUMO__NOT_MOUNTED["${recentKeyEmbeddedFilePath}"]="" ; fi
                        if [ ! -z "${parent_src}" ] ; then SUMO__NOT_MOUNTED["$recentKeyParentSrc"]="" ; fi
                        #_log_dbg "!! ADDING MOUNTED RECENT '${original_src}' '$src' '$mntp' for parent too: '$parent_src', $originalLine"
                else
                        SUMO__NOT_MOUNTED["$recentKey"]="$originalLine"
                        SUMO__NOT_MOUNTED["${recentKeyOriginalSrc}"]="$originalLine"

                        #_log_dbg "!! ADDING NOT MOUNTED RECENT '${original_src}' '$src' '$mntp', $originalLine"
                fi

                SUMO__CURRENT_LIST_SIZE_WITHOUT_RECENT=$((${SUMO__CURRENT_LIST_SIZE_WITHOUT_RECENT} + 1))
        done <<< "${SUMO__CURRENT_LIST_WITHOUT_RECENT}"

        SUMO__CURRENT_LIST_WITHOUT_RECENT="${SUMO__CURRENT_LIST_WITHOUT_RECENT_CLEANED}"

        SUMO__CURRENT_LIST_SIZE=${SUMO__CURRENT_LIST_SIZE_WITHOUT_RECENT}
        SUMO__CURRENT_LIST="${SUMO__CURRENT_LIST_WITHOUT_RECENT}"
}


:<<'EOF'
This function is used to build up an history line from the original list line, 
by replacing the label with the current date in format YY-MM-DD HH:MM.
@param [1] list line
@param out updated list line with date in place of label
@param out recent date in format YY-MM-DD HH:MM
@returns always 0.
EOF

Sumo__setDateOfRecentLine()
{
        local __line="$1"
        local -n out_line=$2
        local -n out_recentDate=$3
        if [[ ${__line} =~ ([§]*»§)(.*) ]] ; then
                __seqToRemove=${BASH_REMATCH[1]}
                __line=${__line//${__seqToRemove}/} # Remove old-style indentation
        fi
        #__line=${__line//»§/} # Remove old-style indentation
        #echo "Sumo__setDateOfRecentLine ${__line}" >&2
        local __leftOfLabel=${__line%%§§*} # Line formatting
        local __rightOfLabel=${__line#*§§} # All line but formatting
        local __rightOfLabelWithoutLabel=${__rightOfLabel#* } # All line but formatting and label
        #_log_dbg "__leftOfLabel:'$__leftOfLabel'" 
        #_log_dbg "rightOfLabelWithoutLabel:'$rightOfLabelWithoutLabel'"         
        local __recentDate="$(date +"%F§%R")"
        out_line="${__leftOfLabel}§§${__recentDate} ${__rightOfLabelWithoutLabel}"
        out_recentDate="${__recentDate}"
        return 0
}

:<<'EOF'
This function is used to update the saved recent mount list after a mount/unmount was carried out by command line.

If there was no entry in the recent list file, an entry for the source is created for it. 
If an entry was already existing, the recorded date is updated to the current date/time.

ATTENTION
    This function calls Dev__getDeviceMapper, which may result in the log "Device sdb1 not found\nCommand failed."
    This is however harmless, because a device mapper is not always available and the original specified device is then used.

@param [1] source which was mounted/unmounted
@param [2] mountpoint (target or past pne)
@param [3] Full disk file path if the device is a disk file
@param [4] operation done: "mount" or "unmount" 
EOF

Sumo__updateSavedRecentList()
{
        if ${SUMO__VARS["HISTORY_GHOST"]} ; then
                return 0
        fi
        local src="$1"
        local original_src="$1"
        local mntp="$2"
        local diskfilepath="$3"
        local operation="$4"
        local currentRecentLine=""
        local mntp_realpath="$(realpath -m "$mntp")"

        local escapedSrc=${src// /§} # not likely
        local escapedOriginalSrc=${original_src// /§} # not likely
        local escapedMntp=${mntp// /§}
        local escapedMntpRealpath=${mntp_realpath// /§}
        Str__trimOnce "$escapedSrc" escapedSrc
        Str__trimOnce "$escapedMntp" escapedMntp

        # When unmounting an overlay using the mounted folded, the resolved source device is 'none'
        # We don't want to save that
        if [ "$src" = "none" ] ; then
                return 0
        fi

        # Shrink those src and mountpoint values that will be shown in the list
        local shrunkSrc="$escapedSrc"                           # USED FOR THE DISPLAY, CAN BE MANGLED
        if Str__startsWith "$shrunkSrc" "nfs://" ; then
                Str__toTail shrunkSrc "nfs://"  last
        fi
        local shrunkMntp="$escapedMntp"
        Str__shrinkToMid shrunkSrc 30 "..."
        Str__shrinkToMid shrunkMntp 30 "..."

        #echo "updateSavedRecentList '$src' '${mntp}' disk file: '${diskfilepath}' operation='$operation'" >> "dbg.txt"

        local metricsHeader="[$((6+${#shrunkSrc}+${#shrunkMntp}+9)),9,1,1,1,1,1,1,${#shrunkSrc},2,${#shrunkMntp}]"
        
        # Disk file?
        local keyForRecent="$escapedSrc"
        if [ ! -z "${diskfilepath}" ] && [ "$src" == "$diskfilepath" ] ; then
                Sumo__getRecentIndirection "$src" keyForRecent
        elif [ ${SUMO__VARS["DO_UNMOUNT"]} -ne 0 ]; then
                # When mounting, the actual device to use as key shall be the device mapper
                if [ -b "$src" ] || [ -c "$src" ] ; then                        
                        Dev__getDeviceMapper "$src" "${Dev__mapperdir}/" keyForRecent 

                        #_log_dbg "Sumo__updateSavedRecentList found device mapper '$keyForRecent' for $src" 
                fi
        fi                

        #echo "updateSavedRecentList '$src' '${mntp}' disk file: '${diskfilepath}' operation='$operation', keyForRecent=$keyForRecent" >> "dbg.txt"

        # The fifth argument enables to force a mountsource value different from the key. It is used for the overlay FS, where the full path of upperdir and lower dir are supplied
        if [ $# -ge 5 ] ; then
                escapedSrc=${5// /§} # not likely
        fi

        if [ -v SUMO__RECENT["$keyForRecent"] ] ; then
                currentRecentLine="${SUMO__RECENT["$keyForRecent"]}"
                # update /mountsource, /mountpoint
                #echo "updateSavedRecentList recent for '$src' exists: '${currentRecentLine}'" >> "dbg.txt"
        else   
                if [ -z "${diskfilepath}" ] ; then
                        currentRecentLine="${metricsHeader}§§- - - - - - ${shrunkSrc} § ${shrunkMntp} |/mountsource:${escapedSrc}|mountpoint:${escapedMntp}|mountpoint_realpath:${escapedMntpRealpath}"
                        #echo "updateSavedRecentList insert new for '$src' '${currentRecentLine}'" >> "dbg.txt"
                else
                        local escapedDiskPath=${diskfilepath// /§} # not likely
                        local escapedDiskBasename=${escapedDiskPath##*/}
                        if [ "$src" == "$diskfilepath" ] ; then
                                currentRecentLine="${metricsHeader}§§- - - - - - ${escapedDiskBasename} § ${shrunkMntp} |/mountsource:${escapedSrc}|mountpoint:${escapedMntp}|mountpoint_realpath:${escapedMntpRealpath}|full§disk§file§path:${escapedDiskPath}"
                                #echo "updateSavedRecentList insert new for disk file '$src' '${currentRecentLine}'" >> "dbg.txt"
                        else
                                #echo "updateSavedRecentList NOTHING TO DO for '$src' '${currentRecentLine}'" >> "dbg.txt"
                                return 0
                                #currentRecentLine="${metricsHeader}§§- - - - - - ${shrunkSrc} § ${shrunkMntp} |/mountsource:${escapedSrc}|mountpoint:${escapedMntp}|mountpoint_realpath:${escapedMntpRealpath}|embedding§disk§file§path:${escapedDiskPath}"
                        fi
                fi
                #echo  "updateSavedRecentList  create recent for '$src' : '${currentRecentLine}'" >> "dbg.txt"
                if Net__isCloudDevice "$src" ; then
                        local cloudURL="<unknown>"
                        Sumo__cloud_getURL cloudURL
                        currentRecentLine="${currentRecentLine}|/real§source:${cloudURL}|system§device:${src}"
                fi

        fi
        local newLine=""
        local recentDate=""
        Sumo__setDateOfRecentLine "$currentRecentLine" newLine recentDate

        SUMO__RECENT["$keyForRecent"]="$newLine"

        # TODO: check the relevancy of this code , because src is not modified. 
        # Probably it is the recent
        if [ "$keyForRecent" != "$original_src" ] ; then
                unset SUMO__RECENT["$escapedOriginalSrc"] # Erase initial one
        fi

        # On unmount, don't keep history of /dev/mapper mapping devices, which are temporary
        # Once unmounted , it dev mapper disappears and therefore won't appear in the internal list of
        # interactive console
        if Str__startsWith "$keyForRecent" "${Dev__mapperdir}" && [ "$operation" = "unmount" ]; then
                SUMO__RECENT["$keyForRecent"]=""
                unset SUMO__RECENT["$keyForRecent"]
                #_log_dbg "unsetting SUMO__RECENT["$keyForRecent"]"
        fi

        # Don't keep history of loop devices having no disk file attached to it
        # TODO THIS WORKS IN ALL CASE BECAUSE LOOP ARE FILTERED IN INTERACTIVE.
        # BUT WHAT HAPPENS IF loops ARE NOT FILTERED??
        local originalLine=""
        for key in "${!SUMO__RECENT[@]}"
        do 
                originalLine="${SUMO__RECENT["$key"]}"
                local __rightOfHeader=${originalLine#*§§} # All line but formatting
                local __rightOfHeaderWithoutLabel=${__rightOfHeader#* } # All line but formatting and label
                local __devType=${__rightOfHeaderWithoutLabel%% *} # Line formatting
                if [ "${__devType}" = "loop" ] ; then
                        #echo "====> FOUND loop ! key: '$key' devtype:'$__devType' for $originalLine">> "dbg.txt"
                        SUMO__RECENT["$key"]=""
                        unset SUMO__RECENT["$key"]
                fi
        done

        _saveRecentList
        local saveRet=$?
        case $saveRet in
                1) _log_err "failed to save recent file list: file is locked." ;;
                2) _log_err "failed to save recent file list: failed to get config folder (err=2)." ;;
                *) ;;
        esac
        return $saveRet
}


:<<'EOF'
This function is dedicated to the display of the formatted device list as constructed by the awk code.

If the interactive mode is active, this function is automatically called by Input__cursorSelect while handling
the user input. In this mode, the 20 lines following the displayed list are erased.

It has also the ability to handle the data transmitted in the hidden column, which starts with '§§' at the end of a row line.
In particular:
- it displays the row in red for duplicated mounts
- it resets the color settings at the end of a displayed row list.

@param [1] the current selected index, mostly useful in interactive mode.
EOF

Sumo__printList()
{
        #_log_dbg "Sumo__printList '$1'"

        #local currentDeviceLocation="$(findmnt -n "/" -o SOURCE)"

        # Save current cursor position from which the list being printed.
        # It will be restored when list needs to be redisplayed in interactive mode
        if [ ! -z "${SUMO__LIST_CURRENT_HELP_CALLBACK}" ] && [ $1 -ne ${SUMO__CURRENT_SELECT_INDEX} ]; then
                SUMO__LIST_CURRENT_HELP_CALLBACK=""
        fi

        SUMO__CURRENT_SELECT_INDEX=$1
        local selectedItemIdx=0
        local tableTitle=$(cat<<EOF        
$(Str__spaces $(($SUMO__LIST_LINE_WIDTH-1)))
Devices
EOF
)     
        local vRightSep=' '
        local vLeftSep='|'
        local extraPadding=1

        if [ ${SUMO__VARS["NO_HEADER"]} -eq 0 ] || [ ${SUMO__VARS["SURROUNDING_FRAME"]} -ne 0 ] ; then
                vLeftSep=""
        fi

        Term__listLinesCounter=0
        if [ ! -z "${SUMO__VARS["INTERACTIVE"]}" ]  ; then
                #printf '\033[f' # Got to the top of the screen
                tput cup 0 0
                #tput ed
        fi


:<<'EOF'
        if [ ${SUMO__VARS["NO_HEADER"]} -eq 0 ] ; then
                extraPadding=0
        fi
EOF
        extraPadding=0

        if [ ${SUMO__VARS["NO_HEADER"]} -ne 0 ] && [ ${SUMO__VARS["SURROUNDING_FRAME"]} -eq 0 ] ; then
                #Term__printBanner "$tableTitle" "_" "|" "$vRightSep" "-" 0 0
                Term__eraseCurrentLine
                Term__printBanner "$(Str__spaces $(( $SUMO__LIST_LINE_WIDTH - 1 )))"  "_" "|" "$vRightSep" "-" 0 2
                Term__printBanner "$(Str__spaces $(( $SUMO__LIST_LINE_WIDTH - 1 )))" "_" "$vLeftSep" "$vRightSep" "-" 0 3
        fi

        if [ ${SUMO__VARS["NO_HEADER"]} -ne 0 ] || [ ! -z "${SUMO__VARS["INTERACTIVE"]}" ] ; then        
                # Display table title, disable any coloring scheme for the tables row
                local old_Term__useListLinesColors=${Term__useListLinesColors}
                Term__useListLinesColors=1
                Term__eraseCurrentLine
                printf '\033[1;44m\033[1;37m' # clear color settings
                Term__printTableRow "$colsTitleAsString" "$SUMO__COLS_WIDTH" "$vLeftSep" "$vRightSep" "" $extraPadding
                printf '\033[0m' # clear color settings
                printf '\n'
                Term__useListLinesColors=${old_Term__useListLinesColors}
        fi

        if [ ${SUMO__VARS["NO_HEADER"]} -ne 0 ] && [ ${SUMO__VARS["SURROUNDING_FRAME"]} -eq 0 ] ; then
                Term__eraseCurrentLine
                # Empty line between bottom of table title header and the columns titles
                if [ ${SUMO__VARS["NO_HEADER"]} -ne 0 ] ; then
                        Term__printBanner "$(Str__spaces $(( $SUMO__LIST_LINE_WIDTH - 1 )))" "_" "$vLeftSep" "$vRightSep" "-" 0 3
                else
                        Term__printBanner "$(Str__spaces $(( $SUMO__LIST_LINE_WIDTH - 1 )))" "_" "$vLeftSep" "$vRightSep" "-" 0 3
                fi
        fi
        
        # The rows
        Term__listLinesCounter=0    
        local insideDetailsSection=1
        while IFS= read -r originalLine
        do 
                #if Str__startsWith "$originalLine" "/ignore:" ; then
                #        continue
                #fi

#echo "print list current index=${SUMO__CURRENT_SELECT_INDEX}  LINE='$originalLine'" >> dbg.txt
                local lineFormatting="${originalLine%%§§*}" # Formatting field starting every field, ended with  §§

                local line="${originalLine% *}"  # Line without hidden data column (last field)
                local rawLine=${line#*§§}
                # Manage current item highlighting
                if [ $Term__listLinesCounter -eq $(($SUMO__CURRENT_SELECT_INDEX-1)) ] ; then
#echo " formating rawline" >> dbg.txt
                        line=${lineFormatting}'\033[7m§§'${rawLine}
                        SUMO__CURRENT_ROW="${originalLine}"
                fi
:<<'EOF'
                local allFieldButLast="${rawLine% *}"
                local allField2Last="${allFieldButLast% *}"
                local fieldSource="${allField2Last##* }"
                local rawFieldSource=${fieldSource#*§}
EOF
                Term__eraseCurrentLine
                #_log_dbg " MY LINE: '$line'n SUMO__COLS_WIDTH='${SUMO__COLS_WIDTH}'"

                Sumo__list_replaceString line
                Term__printTableRow "$line" "$SUMO__COLS_WIDTH" "$vLeftSep" "$vRightSep" "" $extraPadding

                printf '\033[0m' # clear color settings
                printf "\n"

        done <<< "${SUMO__CURRENT_LIST}"

        # Print the input prompt in interactive mode
        if [ ! -z "${SUMO__VARS["INTERACTIVE"]}"  ] ;  then                
                Sumo__im_printPromptLine              # Print the prompt line inclusive statistics                
                printf '\033[s'
                Sumo__list_showCurrentSelectDetails     # Print the details for the current row
        fi

        # Display additional help message
        Sumo__list_printHelp

        # Bottom line of the enclosing frame
        if [ ${SUMO__VARS["NO_HEADER"]} -ne 0 ] && [ ${SUMO__VARS["SURROUNDING_FRAME"]} -eq 0 ] ; then
                Term__eraseCurrentLine
                Term__printBanner "$(Str__spaces $(( $SUMO__LIST_LINE_WIDTH - 1 )))" "_" "$vLeftSep" "$vRightSep" "-" 0 1
        fi

        # Clear bottom screen when neither details nor help message are shown
        if [ -z ${SUMO__LIST_CURRENT_HELP_CALLBACK} ] && [ ${SUMO__VARS["SHOW_DETAILS"]} -ne 0 ]  ; then
                if [ ! -z "${SUMO__VARS["INTERACTIVE"]}"  ] ; then
                        printf '\033[s'
                        tput ed
                        #tput rc
                        printf '\033[u' 
                        #printf '\033[f' # ensure cursor is at the top
                fi
        fi
        return 0
}

Sumo__list_replaceString()
{
        local -n __in_out_line=$1
        if [ ! -z "${SUMO__VARS["REPLACE_IN_LIST"]}" ] ;  then
                local oldString="${SUMO__VARS["REPLACE_OLD_STRING"]}"
                local newString="${SUMO__VARS["REPLACE_NEW_STRING"]}"
                __in_out_line=${__in_out_line//$oldString/$newString}
        fi
}

Sumo__help_showLog()
{
        local nbMaxDetailsSectionLines="${SUMO__VARS["nbMaxDetailsSectionLines"]}"
        # We limit the number of log lines to take into account the fact there may be lines occupying
        # more than 1 terminal line. Leave also some margin.
        local nbbMaxLogLines=$((nbMaxDetailsSectionLines - 3))
        tail -n "$nbbMaxLogLines" "${__LOG_FILE__}"
}

:<<'EOF'
Displays the additional information related to the mounted item
EOF

Sumo__list_printHelp()
{
        if [ ! -z "${SUMO__LIST_CURRENT_HELP_CALLBACK}" ] ; then
                local helpDoc="$(eval "${SUMO__LIST_CURRENT_HELP_CALLBACK}")"
                #echo "$helpDoc"
                # Term__moveCursorUp is bad, because the number of lines displayed
                # may be greater if any detail line is greater than the terminal width
                # and is displayed across several lines
                #printf "JOE! nbline upward:%d"  ${SUMO__VARS["NB_SHOWN_DETAIL_LINES"]} 
                #if [ ${SUMO__VARS["NB_SHOWN_DETAIL_LINES"]} -ne 0 ] ; then
                #        Term__moveCursorUp $((${SUMO__VARS["NB_SHOWN_DETAIL_LINES"]})) 
                #fi                
                printf '\033[u' 
                tput ed
                echo
                local hline=""
                while IFS='' read -r hline
                do
                        echo "$hline"
                done <<<"$helpDoc"
        fi
}

:<<'EOF'
Displays the prompt line in interactive mode
EOF

Sumo__im_printPromptLine()
{
        if [ ! -z "${SUMO__VARS["INTERACTIVE"]}"  ] ;  then                
                local pos;
                if [ ${SUMO__VARS["SHOW_HISTORY"]} -eq 0 ] ; then
                        pos=$((1+${SUMO__CURRENT_LIST_SIZE} + 1 + ${SUMO__CURRENT_RECENTLIST_SIZE}))
                else
                        pos=$((1+${SUMO__CURRENT_LIST_SIZE}))
                fi
                tput cup $pos 0        

#\033[0m\\033[1;42m\\033[1;30m

                Term__eraseCurrentLine                                
                printf "${_pal["white"]}${_pal["bg_green"]}"$'\U21F5'" "$'\U21F1'" "$'\U21F2'" \
${_pal["black_underline"]}${_pal["bg_green"]}\\U23CE ${_pal["black"]}${_pal["bg_green"]}(un)mount \
${_pal["white_underline"]}${_pal["bg_green"]}r${_pal["white"]}${_pal["bg_green"]}emount ro/rw \
${_pal["black_underline"]}${_pal["bg_green"]}q${_pal["black"]}${_pal["bg_green"]}uit \
${_pal["white_underline"]}${_pal["bg_green"]}d${_pal["white"]}${_pal["bg_green"]}etails \
${_pal["black_underline"]}${_pal["bg_green"]}h${_pal["black"]}${_pal["bg_green"]}istory \
${_pal["white_underline"]}${_pal["bg_green"]}i${_pal["white"]}${_pal["bg_green"]}nfo \
${_pal["black"]}${_pal["bg_green"]}lo${_pal["black_underline"]}${_pal["bg_green"]}g${_pal["black"]}${_pal["bg_green"]}s \
${_pal["white_underline"]}${_pal["bg_green"]}u${_pal["white"]}${_pal["bg_green"]}pdate \
${_pal["black_underline"]}${_pal["bg_green"]}b${_pal["black"]}${_pal["bg_green"]}rowse "

                if [ ${SUMO__CURRENT_SELECT_INDEX} -gt ${SUMO__CURRENT_LIST_SIZE} ] ; then
                        #_log_dbg "keyShortcutsConfig: adding 'e' $SUMO__CURRENT_SELECT_INDEX >  ${SUMO__CURRENT_LIST_SIZE} "        
                        printf "${_pal["white_underline"]}${_pal["bg_green"]}e${_pal["white"]}${_pal["bg_green"]}rase history "
                else
                        printf "${_pal["white_underline"]}${_pal["bg_green"]}l${_pal["white"]}${_pal["bg_green"]}abel "
                        printf "${_pal["black_underline"]}${_pal["bg_green"]}f${_pal["black"]}${_pal["bg_green"]}ormat "
                        printf "${_pal["white_underline"]}${_pal["bg_green"]}F${_pal["white"]}${_pal["bg_green"]}lash "
                        printf "${_pal["black_underline"]}${_pal["bg_green"]}P${_pal["black"]}${_pal["bg_green"]}artition "
                fi

                printf "\033[0m \e[0;41m ${__LOG_NB_ERR__}\033[0m\e[0;43m ${__LOG_NB_WARN__}\033[0m\\033[1;42m ${__LOG_NB__}\033[0m"

                printf "\033[0m \n"
        fi
}

:<<'EOF'
Show the detailed information for the current selected device of the list
EOF
Sumo__list_showCurrentSelectDetails()
{
        tput ed
        if [ ${SUMO__VARS["SHOW_DETAILS"]} -eq 0 ] ; then
                SUMO__VARS["NB_SHOWN_DETAIL_LINES"]=0
                # Show the hidden data of the current selection
                Sumo__list_decodeHiddenData "${SUMO__CURRENT_ROW}" SUMO_DETAIL_HIDDEN_DATA_MAP SUMO_DETAIL_RANKS_DATA_MAP
:<<'EOF'                
                if [ ${#SUMO_DETAIL_HIDDEN_DATA_MAP[@]} -gt 0 ] ; then
                        SUMO__VARS["NB_SHOWN_DETAIL_LINES"]=3
                        tput smul
                        printf "\nDetails"
                        tput rmul
                        printf "\n"
                fi
EOF
                local k=0
                local additionalDetailLines=""
                local kmax=${#SUMO_DETAIL_RANKS_DATA_MAP[@]}

                while [ $k -le $kmax ] # First field at index 0 is always empty and skipped
                do
                        local key="${SUMO_DETAIL_RANKS_DATA_MAP[$k]}"
                        #printf "For k=%d, key='%s' " $k $key
                        if [ ! -z "$key" ] ; then                        
                                if ! Str__startsWith "$key" "/" || [ ! -z "${__LOG_DEBUG__}" ]; then
                                        #_log_dbg "$key : ${SUMO_DETAIL_HIDDEN_DATA_MAP["$key"]}"
:<<'EOF'
                                        if [ -z "$additionalDetailLines" ] ; then
                                                additionalDetailLines=" $key : ${SUMO_DETAIL_HIDDEN_DATA_MAP["$key"]}"
                                        else
                                                additionalDetailLines="${additionalDetailLines}
 $key : ${SUMO_DETAIL_HIDDEN_DATA_MAP["$key"]}"
                                        fi
EOF
                                        local keyValue="${SUMO_DETAIL_HIDDEN_DATA_MAP["$key"]}"
                                        local detailLine="$key : $keyValue"
#echo "Sumo__list_showCurrentSelectDetails term heigh: size of detail line: ${#detailLine} ${SUMO__VARS["CURRENT_TERM_HEIGHT"]} x ${SUMO__VARS["CURRENT_TERM_WIDTH"]}" >> "dbg.txt"

                                        Str__shrinkToRight detailLine $(( ${SUMO__VARS["CURRENT_TERM_WIDTH"]} - 2)) "..."
                                        additionalDetailLines="${additionalDetailLines}
 $detailLine"

                                        SUMO__VARS["NB_SHOWN_DETAIL_LINES"]=$(( ${SUMO__VARS["NB_SHOWN_DETAIL_LINES"]} + 1 ))
                                fi
                        fi
                        k=$(($k+1))
                done
                Sumo__list_replaceString additionalDetailLines
                echo "${additionalDetailLines}"
        else
                SUMO__VARS["NB_SHOWN_DETAIL_LINES"]=0
        fi
}

Sumo__list_decodeHiddenMetrics()
{
        local __row="$1"
        local -n out_metricsMap=$2
        local lineFormatting="${__row%%§§*}" 
        if [[ ${lineFormatting} =~ ^\[([^\]]+)\](.*) ]] ; then
                local metrics="${BASH_REMATCH[1]}"
                local metricsItems=()
                readarray -t -d',' metricsItems <<< "${metrics}"                
                out_metricsMap["line_width"]=${metricsItems[0]}
                out_metricsMap["nb_cols"]=${metricsItems[1]}
                local i=0
                while [ $i -lt ${#metricsItems[@]} ]
                do
                        local metric=${metricsItems[$((2+$i))]}
                        if [ ! -z "$metric" ] ; then
                                out_metricsMap["$i"]="$metric" 
                        fi
                        i=$(($i + 1))
                done
:<<'EOF'
                # For debug
                for i in "${!out_metricsMap[@]}"
                do
                        _log_dbg "Sumo__list_decodeHiddenMetrics value[$i]=${out_metricsMap[$i]}, metrics : '$metrics' metrics array=${metricsItems[@]}"
                done
EOF
                return 0
        else
                return 1
        fi
        
}

:<<'EOF'
Extracts the data contained in the last hidden column of a list row.
@param [1] raw list row as produced by awk script
@param [2] out the variable name that where to store the hidden data
EOF

Sumo__list_decodeHiddenData()
{
        local __row="$1"
        local -n out_hiddenFieldsMap=$2
        local -n out_hiddenFieldsRankMap=$3
        local __hiddenDataDec
        out_hiddenFieldsMap=()
        out_hiddenFieldsRankMap=()
        Sumo__list_getHiddenData "${__row}" __hiddenDataDec
#_log "row: '$__row' hidden data: '$__hiddenDataDec'"
        local __hiddenFields=()
        local i=0
        readarray -t -d'|' __hiddenFields <<< "${__hiddenDataDec}"
# _log "fields: ${__hiddenFields[@]}"
        while [ $i -lt ${#__hiddenFields[@]} ]
        do
              local __hiddenField="${__hiddenFields[i]}"
              Str__trimOnce "$__hiddenField" __hiddenField 
#_log "field: '${__hiddenField}'"
              local __propPair=()
              readarray -t -d':' __propPair <<< "${__hiddenField}"
              local __propName="${__propPair[0]}"
              local __propVal="${__propPair[1]}"
              local __cnt=2
              # in case the value contains itself the : separator, append all the remaining fields!
              while [ ${__cnt} -lt ${#__propPair[@]} ] ; do 
                local nextVal="${__propPair[${__cnt}]}"
                Str__trimOnce "$nextVal" nextVal
                __propVal="${__propVal}:${nextVal}" ;
                __cnt=$((${__cnt} + 1))
              done

              # Restore escaped spaces
              __propVal=${__propVal//§/ }
              Str__trimOnce "$__propName" __propName
              Str__trimOnce "$__propVal" __propVal
#_log "prop: '${__propName}' '${__propVal}'"
              if [ ! -z "${__propName}" ] ; then
                out_hiddenFieldsMap[${__propName}]="$__propVal"
                out_hiddenFieldsRankMap[$i]=${__propName}
              fi
              i=$(($i + 1))                
        done        
}

:<<'EOF'
Extracts the data contained in the last hidden column of a list row.
@param [1] raw list row as produced by awk script
@param [2] out the variable name that where to store the hidden data
EOF

Sumo__list_getHiddenData()
{
        local __row="$1"
        local -n out_hiddenData=$2
        local __hiddenData=${__row##* } # Hidden data on last column 
        Str__trimOnce "$__hiddenData" __hiddenData 
        Str__trimOnce "$__hiddenData" __hiddenData §
        out_hiddenData=${__hiddenData//§/ }
        #_log "tmp '${!out_hiddenData} $out_hiddenData'"
}

:<<'EOF'
Outputs the values of internal variables in YAML format.
Currently, mainly used for dev and debug purposes
EOF

Sumo__toYAML()
{
        local v
        echo "---"
        for v in "${!SUMO__VARS[@]}"
        do
                echo "$v: ${SUMO__VARS[$v]}"
        done        
}

:<<'EOF'
This function enables to read the creation parameters specified 
with option -o. It parses arguments of the form <name>=<value>

Currently it accepts the sumo specific parameter size=<disk size>.
The rest is passed on as is to the mount option -o.

@param [1] the full string given as value to -o option.
EOF

Sumo__readCreationParameters()
{
        # for testing : arg="size=10M,vol=2,area"
        local arg="$1"
        allCParams=($(echo "$arg"|awk  -F',' '{ for(i=1;i<=NF;i++) printf("%s ",$i) }'))
        for CParam in "${allCParams[@]}"
        do
                local pname="$(awk -F'=' '{print$ 1}'<<<"$CParam")"
                local pvalue="$(awk -F'=' '{print$ 2}'<<<"$CParam")"
                SUMO__CREATION_OPTIONS["$pname"]="$pvalue"
                if [ "$pname" != "size" ] ; then
                        if [ ! -z "${SUMO__VARS["MOUNT_OPTIONS"]}" ] ; then
                                SUMO__VARS["MOUNT_OPTIONS"]="${SUMO__VARS["MOUNT_OPTIONS"]},"
                        fi
                        SUMO__VARS["MOUNT_OPTIONS"]="${SUMO__VARS["MOUNT_OPTIONS"]}${CParam}"
                fi
        done
}

:<<'EOF'
Load dependencies 
There are 2 kind of deps:
- application level dependencies, with logical names which can imply the loading of multiple system level packages
- the raw system level packages. APT is used by default

Accepted logical names: "all", "google-drive-ocamlfuse", "smb", "luks", "vera", "virt". Any other name is passed on to apt.
EOF

Sumo__loadDep() {
        #echo "+++++++++++++++++++++++++++++++ $@" # DEBUG
        local allDepNames=("$@")
        local loadDone=1
        if [ $# -eq 0 ] ; then
                allDepNames=("all")
        fi
        local c=""
        local ocamlfuse_pkg="google-drive-ocamlfuse"
        #_log_dbg "Sumo__loadDep: trying to install dependencies ${allDepNames[@]}"
        for c in "${allDepNames[@]}"
        do
                #_log_dbg "Sumo__loadDep '$c'"  
                if [ "$c" == "${ocamlfuse_pkg}" ] || [ "$c" == "all" ] ; then
                        Sumo__cloud_loadDep "${ocamlfuse_pkg}"
                elif [ "$c" == "virt" ] || [ "$c" == "all" ] ; then
                        Sumo__virt_loadDep
                elif [ "$c" == "smb" ] || [ "$c" == "all" ] ; then
                        Pkg__install "smbclient" "" apt 
                        Pkg__install "cifs-utils" "" apt 
                elif [ "$c" == "luks" ] || [ "$c" == "all" ] ; then
                        Sumo__luks_loadDep "luks"
                elif [ "$c" == "vera" ] || [ "$c" == "all" ] ; then
                        Sumo__vera_loadDep
                else
                        # By default apt
                        Pkg__install "$c" "" apt 
                        #_log_warn "Do not know how to load dependency named $c"
                fi

                if [ $? -ne 0 ] ; then
                        _log_err "Failed to load dependency named $c"
                        return 1
                fi
        done
        
        # This might add 100ms startup if a several (10) needs to be loaded
        # Cache is written on exit
        #_writeDependenciesCache 
        # 
        return 0
}

:<<'EOF'
Ensures a fault-less quitting of the shell,
deactivating the cleanup() trap.
By default when no second arg is supplied, exits with code 0, otherwise with the specified code
@param [1] goodbye message
@param [2] optional error code (0 by default)
EOF

Sumo__quit() {
        local msg="$1"
        local exitCode=0
        if [ $# -eq 2 ] ; then
                exitCode=$2
        fi

        Sys__sweep "findmnt" "--poll"

        trap - EXIT SIGHUP SIGINT SIGTERM SIGQUIT SIGABRT
        Term__reset
        if [ -z "${SUMO__VARS["CALLER"]}" ] && [ ! -z "${SUMO__VARS["INTERACTIVE"]}" ]; then
            Term__exitPrivateBufferMode    
        fi
        tput ed
        _exit $exitCode "$msg"
}

:<<'EOF'
Shell cleanup callback upon arising of a system signal:
- resets terminal setttings.
- removes any created directory which was mounted.

The allocated loop device are removed. They can reused to remount the related disk file.
When disk files are mounted in cascade, the loop device associated with nested file systems must be detached,
otherwise the parent device is marked as 'busy' and cannot be unmounted.
EOF

Sumo__cleanup() {
        Term__reset
        if [ -z "${SUMO__VARS["CALLER"]}" ] && [ ! -z "${SUMO__VARS["INTERACTIVE"]}" ]; then
            Term__exitPrivateBufferMode   
        fi

        Sumo__im_stopMountMonitoring

        _log_dbg "Cleanup of devices"
        if [ ! -z "${SUMO__VARS["DEV"]}" ] && ! Sumo__checkIfAnyMount; then
                if Dev__deactivateAllVolumeGroupsForDisk "${SUMO__VARS["DEV"]}" ; then
                        _log_dbg "Successfully removed volume groups for ${SUMO__VARS["DEV"]}"
                        if [ -z "${SUMO__VARS["SILENT"]}" ] ; then 
                                _log "Cleaning up ${SUMO__VARS["DEV"]}"
                        fi
                        if [ "${SUMO__VARS["BLK_TYPE"]}" == "loop" ] ; then   #if [ "$(lsblk "${SUMO__VARS["DEV"]}" --noheadings -o TYPE|head -n1)" == "loop" ] ; then
                                ${__SUDO__}/sbin/losetup -d "${SUMO__VARS["DEV"]}" &> /dev/null
                        elif [ "${SUMO__VARS["BLK_TYPE"]}" == "nbd" ] ; then
                                Sumo__virt_nbd_close "${SUMO__VARS["DEV"]}" &> /dev/null
                        fi
                fi
        fi

        # and let exit according to the raised signal
        _log_dbg "Sumo__cleanup with exit code $1"
        if [ $1 -ne 0 ] ; then
                if [ ${SUMO__VARS["MOUNT_POINT_CREATED"]} -eq 0 ] ; then
                        #if [ -z "${SUMO__VARS["LAZY"]}" ] ; then
                                if [ -z "$(ls -1 "${SUMO__VARS["MOUNT_POINT"]}" &>/dev/null)" ] ; then
                                        if rmdir "${SUMO__VARS["MOUNT_POINT"]}" 2>/dev/null; then 
                                                if [ -z "${SUMO__VARS["SILENT"]}" ] ; then 
                                                        _log_dbg "Successfully removed the created mount folder '${SUMO__VARS["MOUNT_POINT"]}'."
                                                fi
                                        else
                                                _log_err "Failed to remove mount folder '${SUMO__VARS["MOUNT_POINT"]}'. Please check and cleanup manually."
                                        fi
                                else
                                        _log_warn "Mount folder '${SUMO__VARS["MOUNT_POINT"]}' could not be removed. Please check and cleanup manually."
                                fi
                        #fi
                fi
        fi
}
:<<'EOF'
EOF
Sumo__checkIfAnyMount()
{
        local mntSource
        local mntTarget
        local anyMount=0
        if [ ! -z  "${SUMO__VARS["DEVPART"]}" ] ; then
                local devs=(${SUMO__VARS["DEVPART"]})
                local dev
                for dev in "${devs[@]}" ; do
                        if Dev__findMount "$dev" mntSource mntTarget ; then 
                                return 0
                        fi
                done
        fi
        return 1
}


:<<'EOF'
Retrieves the mounting status and the mount point depending on the passed sumo arguments
and already mounted devices.
EOF

Sumo__resolveBlockDeviceInfos() 
{
        local isVera_and_IsForMountingExisting_and_isFileDefined=1
        if Sumo__isVera && [ ${SUMO__VARS["CREATE_FILE"]} -ne 0 ] && [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] ; then
                isVera_and_IsForMountingExisting_and_isFileDefined=0
        fi

        _log_dbg "Sumo__resolveBlockDeviceInfos"
        if [ "${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]}" -eq 0 ] ; then
                Sumo__resolveBlockDeviceMountingInfos "${SUMO__VARS["IMG_FILE"]}"
                _log_dbg "BY LABEL: DEV='${SUMO__VARS["DEV"]}' DEVPART='${SUMO__VARS["DEVPART"]}' BLK_TYPE=${SUMO__VARS["BLK_TYPE"]}"
        elif [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then 
                _log_dbg "Sumo__resolveBlockDeviceInfos for MOUNT_POINT ${SUMO__VARS["MOUNT_POINT"]}"
                local foundSource="${SUMO__VARS["MOUNT_POINT_SOURCE"]}"

                if [ -z "$foundSource" ] ; then
                        # If a mount folder is specified, resolve the device path and its parent.
                        if Dev__findMountSource "${SUMO__VARS["MOUNT_POINT"]}" foundSource ; then
                                SUMO__VARS["MOUNTED"]=0
                                Sumo__targetsListOfMyselfOwner+=("${SUMO__VARS["MOUNT_POINT"]}")
                                Sumo__devicesOftargetsListOfMyselfOwner+=("$foundSource")
                        fi # else, foundSource is still empty
                fi

                if [ -z "$foundSource" ] ; then    
                        # check for label as well if no mounting info found on folder
                        # This is mainly useful when attempting to create a new image where folder is 
                        # supplied. For other cases, like unmounting and mounting, it is checked
                        # upstream that there are no conflicting/redundant arguments
                        if [ ${isVera_and_IsForMountingExisting_and_isFileDefined} -ne 0 ]; then
                                if ! Sumo__resolveBlockDeviceInfos_FromLabel "${SUMO__VARS["FS_LABEL"]}" ] ; then
                                        if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ]  ; then
                                                Sumo__resolveBlockDeviceInfos_FromDiskFile "${SUMO__VARS["IMG_FILE"]}" "${SUMO__VARS["IMG_DISK_FILE_PATH"]}"
                                        fi
                                fi
                        fi
                else
                        if [ ${SUMO__VARS["DO_UNMOUNT"]} -ne 0 ]; then
                                _quit "Folder ${SUMO__VARS["MOUNT_POINT"]} is already mounted."
                        fi

                        Sumo__resolveBlockDeviceMountingInfos "$foundSource" 1 # 1=do not seek mount points
                fi
        elif [ ! -z "${SUMO__VARS["FS_LABEL"]}" ] && [ ${isVera_and_IsForMountingExisting_and_isFileDefined} -ne 0 ]; then
                Sumo__resolveBlockDeviceInfos_FromLabel "${SUMO__VARS["FS_LABEL"]}"
        elif [ ! -z "${SUMO__VARS["IMG_FILE"]}" ]  ; then
                Sumo__resolveBlockDeviceInfos_FromDiskFile "${SUMO__VARS["IMG_FILE"]}" 
        fi
}

:<<'EOF'
Resolves the mounting information based on the configured image file.
@param [1] the original input filename , which may be a relative path
@param [2] the absolute path corresponding to parameter 1
EOF

Sumo__resolveBlockDeviceInfos_FromDiskFile()
{
        local diskFileName="$1"
        local diskFileAbsPath="$1"

        _log_dbg "${FUNCNAME[0]} for file ${diskFileName}"

        if [ -f "${diskFileName}" ] ; then
                local fullpath="${diskFileAbsPath}"
                if [ -z "$fullpath" ] ; then
                        fullpath="$(realpath -m "$1")"
                fi
                if Sumo__isVera  ; then
                        local mountpoint=""                        
                        Vera__findMountPointFromVolume "$fullpath" mountpoint # OLD SUMO__VARS["MOUNT_POINT"]=$(veracrypt -l|awk -F' ' -v IMG="${fullpath}" '{if ($2==IMG) print $4}' 2>/dev/null)
                        _log_dbg "${FUNCNAME[0]} for VERA file $fullpath, found mountpoint '$mountpoint'"
                        if [ ! -z "$mountpoint" ] ; then

                        #if [ ! -z "$mountpoint" ] && [ "$mountpoint" != "-" ] ; then
                                SUMO__VARS["MOUNTED"]=0
                                SUMO__VARS["MOUNT_POINT"]="$mountpoint"
                                Sumo__resolveBlockDeviceInfos  
                        fi
                else
                        # Test NF==2 enables to exclude cases of '(deleted) devices'
                        local imgtype=""
                        if Sumo__isLuks ; then                                 
                                imgtype="luks"                                  
                        fi

                        if Sumo__isVirt ; then
                                if Sumo__resolveMountingInfosFromNBD "${fullpath}" "${imgtype}" ; then
                                        if  [ -z "${SUMO__VARS["DEVPART"]}" ] ; then
                                                _log_warn "no child block device found for NBD device '${SUMO__VARS["DEV"]}' bound with path '${fullpath}'"
                                        fi                                
                                elif ! Sumo__resolveMountingInfosFromDiskFileRecordedInRecentList "${fullpath}" ; then
                                        _log_dbg "no block device found for path '${fullpath}'" 
                                fi
                        elif Sumo__resolveMountingInfosFromDiskFile "${fullpath}" "${imgtype}" ; then
                                if  [ -z "${SUMO__VARS["DEVPART"]}" ] ; then
                                        _log_warn "no child block device found for loop device '${SUMO__VARS["DEV"]}' bound with path '${fullpath}'"
                                fi
                        elif ! Sumo__resolveMountingInfosFromDiskFileRecordedInRecentList "${fullpath}" ; then
                                _log_dbg "no block device found for path '${fullpath}'" 
                        fi
                fi
        elif [ -e "${diskFileName}" ] ; then
                _exit -30 "'${diskFileName}' is neither a regular disk file nor valid block device."  
        else
                SUMO__VARS["CREATE_FILE"]=0
        fi
        # Example of outout 1: /home/michel/test.vera /dev/mapper/veracrypt1 /home/michel/test           
}

:<<'EOF'
Resolves the mounting information based on the configured label.
EOF

Sumo__resolveBlockDeviceInfos_FromLabel() {
        local label="$1"
        _log_dbg "Sumo__resolveBlockDeviceInfos_FromLabel '${SUMO__VARS["FS_LABEL"]}'"
        if [ ! -z "${label}" ] ; then
                if Sumo__isVera; then
                        local mountpoint=""
                        if Vera__findMountPointFromSlot "${label}" mountpoint ; then
                                #if Sumo__vera_determineIfLabelIsMounted "${label}" ; then
                                if [ ! -z "$mountpoint" ] ; then
                                        SUMO__VARS["MOUNTED"]=0
                                        SUMO__VARS["MOUNT_POINT"]="$mountpoint"
                                        Sumo__resolveBlockDeviceInfos  
                                fi
                        else
                                # Nothing found is just fine at creation of a new image. Only relevant
                                # when attempting to open an existing image
                                if [ ${SUMO__VARS["CREATE_FILE"]} -ne 0 ] ; then
                                        _quit "No vera volume found with slot '${label}'"
                                fi
                        fi
                else
                        # TODO: If multiple devices with same label?
                        SUMO__VARS["DEVPART"]="$(lsblk --paths -n -o NAME,LABEL,TYPE|awk -F' ' -v devtype="${SUMO__VARS["DEVTYPE"]}" -v lbl="${label}" '{ if ( ($2==lbl) && ((devtype=="") || (devtype=$3)) ) { print $1 ; exit 0} }'|sed -E 's/^'${SUMO__VARS["LSBLK_TREE_CHARS"]}'+//g')"                        

                        # With blkid it is more efficient than above line
                        #SUMO__VARS["DEVPART"]="$(blkid  -l -o device -t LABEL="${label}")"
                        _log_dbg "BY LABEL: '${label}' DEV='${SUMO__VARS["DEV"]}' DEVPART='${SUMO__VARS["DEVPART"]}'"
                        if [ ! -z "${SUMO__VARS["DEVPART"]}" ] ; then
                                if [ ${SUMO__VARS["CREATE_FILE"]} -eq 0 ] ; then
                                        _exit -11 "Another device (${SUMO__VARS["DEVPART"]}) is already labelled '${label}'"
                                fi
                                SUMO__VARS["IMG_FILE_IS_BLK_DEV"]=0
                                Sumo__resolveBlockDeviceMountingInfos "${SUMO__VARS["DEVPART"]}"
                        else
                                # Nothing found is just fine at creation of a new image. Only relevant
                                # when attempting to open an existing image
                                if [ ${SUMO__VARS["CREATE_FILE"]} -ne 0 ] ; then
                                        local msg=""
                                        msg="No block device found with label '${label}'"
                                        if [ ! -z "${SUMO__VARS["DEVTYPE"]}" ] ; then
                                                msg="$msg and of type '${SUMO__VARS["DEVTYPE"]}'"
                                        fi
                                        _exit -10 "$msg"
                                fi
                        fi
                fi
                return 0
        else
                return 1
        fi
}

:<<'EOF'
Retrieves the mount point(s) for a given block device. 

Additionally, it initializes :
- DEV with the internal parent device (if any)),
- DEVPART with first argument, or with the matching loop part device for luks
- DEVMAPPER with first argument for luks 
- DEVPART_TYPE with the type of the passed mount source
- BLK_TYPE to 'loop' if possible

@param [1] mount source
@param [2] optional (true by default): boolean telling whether to seek mountpoints (0), or only try to initialize the above variable
@returns 0 if a mount point was found, 1 otherwise
EOF

Sumo__resolveBlockDeviceMountingInfos() {
        #local doProceed=1

        #if ! Args__checkCount "${FUNCNAME[0]}" 1 "$#" "Invalid argument count" ; then return -1 ; fi
        #Sumo__resolveMountingInfos "$1"                
        #doProceed=$?

        if [ $# -eq 1 ] ; then
                Sumo__resolveMountingInfos "$1"                
                #doProceed=0
        elif [ $# -eq 2 ] ; then
                if [ $2 -eq 0 ] ; then
                        Sumo__resolveMountingInfos "$1"                
                        #doProceed=0
                #else
                        # else do not seek mount points, but initialize the vars
                        #doProceed=0
                fi
        else
                Args__checkCount ${FUNCNAME[0]} 2 "$#" "Usage: <mount source> [<boolean>]"
                return $?
        fi


        #if [ $doProceed -eq 0 ]  ; then
                #if [ ${SUMO__VARS["DO_UNMOUNT"]} -eq 0 ]; then
                        # Search for the parent device, which may be an actuall loop device for disk files
                        # DEV may be simply empty if it is an actual block device
                        local devInfo=""
                        local devInfoRes=1
                        devInfo="$(lsblk --paths "$1" --noheadings -o PKNAME,TYPE 2>>"${__LOG_ERR_FILE__}")"  
                        devInfoRes=$?
                        # |sed 's/'${SUMO__VARS["LSBLK_TREE_CHARS"]}'//g')"  # Adding this may only valid when 'NAME' is selected as output
                        local devPath=""
                        local devpartType=""
                        Str__squeeze "$devInfo" devInfo
                        Str__split "$devInfo" devPath " " devpartType
                        SUMO__VARS["DEV"]="$devPath"
                        SUMO__VARS["DEVPART"]="$1"
                        SUMO__VARS["DEVMAPPER"]="$1"
                        SUMO__VARS["DEVPART_TYPE"]="$devpartType"
                        
                        if [ "$devpartType" == "crypt" ] ; then
                                if [ "${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]}" -eq 0 ] ; then
                                        SUMO__VARS["DEVMAPPER"]="$1"
                                fi

                                local ancestryDevMapper=($(lsblk --paths| awk "${SUMO__VARS["AWK_LSBLK_TREE_FLATTENING_CMD_FOR_MOUNT_RESOLVE"]}"| grep -E ${SUMO__VARS["DEVMAPPER"]}$))
                                #_log_dbg "Sumo__resolveBlockDeviceMountingInfos ancestryDevMapper for CRYPT $ancestryDevMapper"
                                if [ ${#ancestryDevMapper[@]} -ge 2 ] ; then
                                        SUMO__VARS["DEVPART"]="${ancestryDevMapper[0-2]}"
                                fi
                                if [ ${#ancestryDevMapper[@]} -ge 3 ] ; then
                                        SUMO__VARS["DEV"]="${ancestryDevMapper[0-3]}"
                                        SUMO__VARS["BLK_TYPE"]="loop"
                                fi
                        elif [ $devInfoRes -eq 0 ] && [ ! -z "$devPath" ] ; then
                                local devType=""
                                devType="$(lsblk --paths "$devPath" --noheadings -o TYPE|head -n1 2>>"${__LOG_ERR_FILE__}")"
                                if [ $? -eq  0 ] ; then
                                        SUMO__VARS["BLK_TYPE"]="$devType"
                                fi
                        fi

                        _log_dbg "Sumo__resolveBlockDeviceMountingInfos DEVMAPPER='${SUMO__VARS["DEVMAPPER"]}' DEV='${SUMO__VARS["DEV"]}' DEVPART='${SUMO__VARS["DEVPART"]}' DEVPART_TYPE='$devpartType' BLOCK_TYPE='${SUMO__VARS["BLK_TYPE"]}'"
                        #exit 0
                #fi
                return 0
        #fi
        return 1
}

:<<'EOF'
Retrieves the mount point(s) for a given source.

@param [1] mount source
@output global Sumo__targetsListOfMyselfOwner the array of found targets when multiple targets where found.
@output global SUMO__VARS["MOUNT_POINT"] and SUMO__VARS["MOUNT_POINT"]. 
        In case of multiple targets, the first target of the list is used to initialize "MOUNT_POINT"
@returns 0 if a mount point was found, 1 otherwise
EOF

Sumo__resolveMountingInfos() {
        _log_dbg "${FUNCNAME[0]} for source '$1'"

        local source="$1"
        local targetDir=""

        # If the preliminary mount resolution based on an input mount point 
        # was already successful, we don't need to continue
        if [ ${SUMO__VARS["DO_UNMOUNT"]} -eq 0 ] && [ ! -z "${SUMO__VARS["MOUNT_POINT_SOURCE"]}" ] && [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ]  ; then
                return 0
        fi

        if Dev__findMountPoint "${source}" targetDir ; then    
                _log_dbg "${FUNCNAME[0]}: found target '$targetDir'"

                if [ ${SUMO__VARS["CREATE_FILE"]} -eq 0 ] ; then
                        _exit -1 "Disk '${SUMO__VARS["IMG_FILE"]}' can not be created. Some parameters conflicts with already mounted source '$source' (conflicting label '${SUMO__VARS["FS_LABEL"]}'?)."
                fi

                local testTargetDir="$targetDir"
                Str__toTail testTargetDir $'\n' last
                local NbFoundTargetsInThisCall=0
                #echo "TAIL :'$testTargetDir' mp='${SUMO__VARS["MOUNT_POINT"]}'"
                if [ "$testTargetDir" != "$targetDir" ] ; then
                        if [ ${SUMO__VARS["DO_UNMOUNT"]} -ne 0 ]; then
                                _log_warn "'${source}' is already mounted multiple times:"
                        else
                                _log_warn "'${source}' is currently mounted multiple times:"
                        fi
                        while IFS='' read -r targetLine
                        do
                                Str__trimOnce "$targetLine" targetLine                        
                                local targetOwner=""
                                targetOwner="$(timeout -s SIGKILL 1 stat -c "%U" "$targetLine")" # %G")
                                if [ -z "$targetOwner" ] ; then
                                        # when stat fails (connection broken?)
                                        # assume current user
                                        targetOwner="${SUMO__VARS["OWNER"]}" 
                                fi
                                _log_warn "- Folder '$targetLine' owned by '$targetOwner'"

:<<'EOF'
                                local confirmedTargetIfDifferentOwnner=true
                                if [ ${SUMO__VARS["DO_UNMOUNT"]} -eq 0 ]; then # Mounting request
                                        if [ "$targetOwner" != "${SUMO__VARS["OWNER"]}" ] ; then
                                                Input__confirm "The owner of folder '$targetLine' is '$targetOwner' and not you (${SUMO__VARS["OWNER"]}). Unmount it anyway?"
                                                confirmedTargetIfDifferentOwnner=$?
                                        fi
                                fi
                                if $confirmedTargetIfDifferentOwnner ; then

EOF
                                # This test was commented out, because when doing ssh
                                # on a login that does not exist locally, the mounted
                                # targets are ignored and targetDir is ultimately empty
                                # Moreover, in the else case below, there's no such test
                                # When unmounting, this can however be dangerous, as other user's
                                # mount could be impacted
                                #if [ "$targetOwner" == "${SUMO__VARS["OWNER"]}" ] ; then
                                Sumo__targetsListOfMyselfOwner+=("$targetLine")
                                Sumo__devicesOftargetsListOfMyselfOwner+=("$source")
                                NbFoundTargetsInThisCall=$(($NbFoundTargetsInThisCall + 1))
                                #fi
                        done <<<"$targetDir"

                        targetDir="${Sumo__targetsListOfMyselfOwner[0]}" # If there are existing multiple points it won't prevent us to mount another
                else
                        NbFoundTargetsInThisCall=1
                        Sumo__targetsListOfMyselfOwner+=("$targetDir")
                        Sumo__devicesOftargetsListOfMyselfOwner+=("$source")
                fi

                if [ ${SUMO__VARS["DO_UNMOUNT"]} -ne 0 ]; then # Mounting request
                        if [ -z  "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                                # Save the mounted mount point only if not already explicitly set by argument
                                SUMO__VARS["MOUNTED"]=0                
                                SUMO__VARS["MOUNT_POINT"]="$targetDir"
                        fi
                        #_quit "${source} mounted on ${SUMO__VARS["MOUNT_POINT"]} is already mounted."
                        if [ $NbFoundTargetsInThisCall -eq 1 ] ; then # do not duplicate warning with above                                
                                _log_warn  "'${source}' already mounted on '${targetDir}'."
                        fi
                else # unmounting request
                        if [ ${#Sumo__targetsListOfMyselfOwner[@]} -ne 1 ] && [ ! -v SUMO__VARS["ALL_FLAG"] ]  ; then
                              _exit -1 "Please unmount by specifying the exact folder name or use option -a to unmount all at once."
                        fi
                        if [ -z "${targetDir}" ]  ; then
                              _exit -1 "No unmount to do. Possibly, you are not the owner of the folder to unmount. In that case, please unmount by specifying the exact folder name to enforce unmounting."
                        fi
                        _log_dbg "${FUNCNAME[0]}: unmounting request case '$targetDir'"
                        SUMO__VARS["MOUNTED"]=0                
                        SUMO__VARS["MOUNT_POINT"]="$targetDir"
                fi
                return 0                
        fi
        #_log_dbg "${FUNCNAME[0]}: no target found !"

        return 1
}

:<<'EOF'
Retrieves the devices for the passed disk files and initializes SUMO__VARS["DEV"], SUMO__VARS["DEVPART"] and SUMO__VARS["BLK_TYPE"]

@param [1] disk files
@param [2] disk file type, e.g. luks or vera

@returns 0 if a matching device was found for the disk file.
EOF

Sumo__resolveMountingInfosFromDiskFile() {        
        local imageFile="$1"
        local type="$2"
        #local devs=($(losetup --list -n -O NAME,BACK-FILE|awk -F' ' -v IMG="${imageFile}" '{ if ((NF==2) && ($2==IMG)) print $1 }' | sort -r 2>/dev/null))
        local devpart=""
        local dev=""
        local first_devpart=""
        local loLine

        _log_dbg "Sumo__resolveMountingInfosFromDiskFile '$1' '$2'"

        while IFS= read -r loLine
        do
                local loLineFields=($loLine)
                local dev="${loLineFields[0]}"
                local boundfile="${loLineFields[@]:1}"
                #_log_dbg "Sumo__resolveMountingInfosFromDiskFile($imageFile) checking line '$loLine' boundfile=$boundfile dev=$dev" 

                if [ "$boundfile" == "$imageFile" ] ; then
                        if [ "$type" == "luks" ] ; then
                                # For LUKS there is one additional indirection level to the /dev/mapper/...
                                devpart=($(lsblk --paths| awk "${SUMO__VARS["AWK_LSBLK_TREE_FLATTENING_CMD_FOR_MOUNT_RESOLVE"]}"| awk -F' ' -v DEV="${dev}" '{if (($1==DEV) && (NF > 2)) {print $3}}'))
                        else
                                devpart=($(lsblk --paths| awk "${SUMO__VARS["AWK_LSBLK_TREE_FLATTENING_CMD_FOR_MOUNT_RESOLVE"]}"| awk -F' ' -v DEV="${dev}" '{if (($1==DEV) && (NF > 1)) {print $2}}'))
                        fi

                        _log_dbg "Sumo__resolveMountingInfosFromDiskFile for type '$type' devpart:'${devpart[@]}'" 

                        if [ ! -z "$devpart" ] ; then
                                local devpartItem
                                local newDevpart

                                for devpartItem in "${devpart[@]}"
                                do
                                        if Sumo__resolveMountingInfos "$devpartItem" ; then
                                                newDevpart+=("$devpartItem")
                                        fi
                                done
                                if [ -z "$first_devpart" ] ; then 
                                        SUMO__VARS["DEV"]="${dev}"
                                        SUMO__VARS["BLK_TYPE"]="loop"    
                                        SUMO__VARS["DEVPART"]="${devpart[@]}"
                                        SUMO__VARS["DEVMAPPER"]="${SUMO__VARS["DEVPART"]}"
                                        first_devpart="done"                           
                                fi
                        fi
                fi
        done < <(/sbin/losetup --list -n -O NAME,BACK-FILE)
       _log_dbg "found '${SUMO__VARS["DEV"]}' '${SUMO__VARS["DEVPART"]}'"
       [ ! -z "${first_devpart}" ]
}

:<<'EOF'
Retrieves the devices for the passed disk files and initializes SUMO__VARS["DEV"], SUMO__VARS["DEVPART"] and SUMO__VARS["BLK_TYPE"]

@param [1] disk files
@param [2] disk file type, e.g. luks or vera

@returns 0 if a matching device was found for the disk file.
EOF

Sumo__resolveMountingInfosFromNBD() {     
        local imageFile="$(realpath -m $1)"
        local type="$2"

        local devpart=""
        local dev=""
        local first_devpart=""
        local psLine
        while IFS= read -r psLine
        do
                local psLineFields=($psLine)
                local dev="${psLineFields[2]}"
                local boundfile="$(realpath -m ${psLineFields[3]})"
                #_log_dbg "Sumo__resolveMountingInfosFromNBD('$imageFile') checking line '$psLine' boundfile='$boundfile' dev=$dev"
                if [ "$boundfile" == "$imageFile" ] ; then
                        devpart=($(lsblk --paths| awk "${SUMO__VARS["AWK_LSBLK_TREE_FLATTENING_CMD_FOR_MOUNT_RESOLVE"]}"| awk -F' ' -v DEV="${dev}" '{if (($1==DEV) && (NF > 1)) {print $NF}}'))
                        if [ ! -z "$devpart" ] ; then
                        	_log_dbg "Sumo__resolveMountingInfosFromNBD: devpart : $devpart"
                                local devpartItem=()
                                local newDevpart
                                for devpartItem in "${devpart[@]}"
                                do
:<<'EOF'
                                        local devpartFS=$(lsblk -n -o FSTYPE "$devpartItem"|head -n1)
                                        if [ "$devpartFS" != "LVM2_member" ] ; then
                                                newDevpart+=("$devpartItem")
                                                Sumo__resolveMountingInfos "$devpartItem"
                                        fi
EOF
                                        if Sumo__resolveMountingInfos "$devpartItem" ; then
                                                newDevpart+=("$devpartItem")
                                        fi
                                done
                                if [ -z "$first_devpart" ] ; then 
                                        SUMO__VARS["DEV"]="${dev}"
                                        SUMO__VARS["BLK_TYPE"]="nbd"    
                                        SUMO__VARS["DEVPART"]="${newDevpart[@]}"
                                        first_devpart="done"                       
                                fi
                        fi
                fi
        done < <(ps -C qemu-nbd -o cmd=)

       _log_dbg "found '${SUMO__VARS["DEV"]}' '${SUMO__VARS["DEVPART"]}' mounted: ${SUMO__VARS["MOUNTED"]} '${SUMO__VARS["MOUNT_POINT"]}'"

       [ ! -z "${first_devpart}" ]
}

:<<'EOF'
EOF

Sumo__resolveMountingInfosFromDiskFileRecordedInRecentList()
{
        local imageFile="$1"
        local key
        for key in "${!SUMO__RECENT[@]}"
        do
                if [ ${#SUMO__NOT_MOUNTED["$key"]} -ne 0 ] ; then
                        if [ "$key" == "$imageFile" ] ; then
                                local val="${SUMO__RECENT["$key"]}"
                                Sumo__list_decodeHiddenData "${val}" SUMO_DETAIL_HIDDEN_DATA_MAP SUMO_DETAIL_RANKS_DATA_MAP
                                #local delegate_device="${SUMO_DETAIL_HIDDEN_DATA_MAP["/delegate-device"]}"
                                local src="${SUMO_DETAIL_HIDDEN_DATA_MAP["/mountsource"]}"

                                stat -L -c "%F" "$assumedBlkDevPath" 2>/dev/null
                                if [ $? -ne 0 ] ; then 
                                        continue; 
                                fi

                                Sumo__resolveMountingInfos "$src"

                                SUMO__VARS["DEV"]="${src}"             
                                SUMO__VARS["DEVPART"]="${src}"
                                SUMO__VARS["DEVMAPPER"]="${SUMO__VARS["DEVPART"]}"
                                if Sumo__isVirt ; then
                                        SUMO__VARS["BLK_TYPE"]="nbd"
                                else
                                        SUMO__VARS["BLK_TYPE"]="loop"
                                fi
                                return 0
                        fi
                fi
        done
        return 1
:<<'EOF'                
                delegate_device="${SUMO_DETAIL_HIDDEN_DATA_MAP["/delegate-device"]}"
                delegate_mntp="${SUMO_DETAIL_HIDDEN_DATA_MAP["/delegate-mountpoint"]}"
                delegate_status="${SUMO_DETAIL_HIDDEN_DATA_MAP["/delegate-status"]}"
                mntp="${SUMO_DETAIL_HIDDEN_DATA_MAP["mountpoint"]}"
                src="${SUMO_DETAIL_HIDDEN_DATA_MAP["/mountsource"]}"
                original_src="$src"
                status="${SUMO_DETAIL_HIDDEN_DATA_MAP["status"]}"
                recentdate="${SUMO_DETAIL_HIDDEN_DATA_MAP["/recent"]}"
                local original_src="$src"
                if [ ! -z "${delegate_device}" ] ; then
                        src="${delegate_device}"
                fi
EOF
}



:<<'EOF'
Luks creates a /dev/mapper based on the passed 
For LUKS :
- If not set, sets FS_LABEL to the core file name of the disk image
- Resolves the device mapper path to /dev/mapper/FS_LABEL, as Luks will do. 
Passed FS_LABEL matters at creation, but not at mounting, since even specifying another label, the inital
is kepted. So the FS_LABEL may be different
- 
- Sets MOUNTED if already mounted
- Bails out with an error when attempting to create a new disk for which there is already another
  system mounted with the same volume label.
EOF

Sumo__initDataLUKS() {
        # Volume name is the core file name
        _log_dbg "Sumo__initDataLUKS START label=${SUMO__VARS["FS_LABEL"]}"

        if [ ! -z "${SUMO__VARS["VOLUME_NAME"]}" ] ; then
                SUMO__VARS["FS_LABEL"]="${SUMO__VARS["VOLUME_NAME"]}"
        elif [ -z "${SUMO__VARS["FS_LABEL"]}" ] ; then
                local corename
                File__corename "${SUMO__VARS["IMG_FILE"]}" corename
                SUMO__VARS["FS_LABEL"]="$corename"
        fi
        #_log_dbg "Sumo__initDataLUKS END label=${SUMO__VARS["FS_LABEL"]}"
        
        SUMO__VARS["DEVMAPPER"]="${Dev__mapperdir}/${SUMO__VARS["FS_LABEL"]}"
}

# To make the mounting permanent, edit  /etc/fstab as follows (e.g. if ext4 partitions=):  <image file> <mount point> ext4  loop

:<<'EOF'
Parse arguments callback:
- Processes argument which are not options (not starting with a dash).
- Processes option values by evaluating SUMO__OPTION_LIST_VALS[<option>], in which case
the option is given by second argumet.

The arguments processed is tracked by a counter passed on by ref. 
The 1st argument is interpreted as device/file
The 2nd argument is interpreted as mount point
 
@param [1] argument value (which can be an option value)
@param [2] previous argument (reference). It should be empty since 'arg'' is not supposed to be an option.
@param [3] arg counter name (reference)
@returns incremented counter 
EOF

Sumo__processDashLessArg()
{
        _log_dbg "Sumo__processDashLessArg '$1' '$2' '$3'"
        local arg="$1"
        local -n _prevarg=$2
        local _arg_cnt=$3

        if Str__startsWith "$arg" "-" ; then
                _susage "unknown option '$arg'"
        fi
        if [ -z "$_prevarg" ] ; then
                case ${_arg_cnt} in
                0) SUMO__VARS["IMG_FILE"]="$arg" ;;
                1) SUMO__VARS["MOUNT_POINT"]="${arg}" ;;                                        
                *) _susage "unexpected argument '$arg'" ;;
                esac
                #_arg_cnt=$(( _arg_cnt + 1 ))
                return $(( _arg_cnt + 1 ))
        else
                if [ ! -z "${SUMO__OPTION_LIST_VALS[$_prevarg]}" ] ; then
                        eval "${SUMO__OPTION_LIST_VALS[$_prevarg]}"
                else
                        _susage "unexpected argument '$arg' following '$_prevarg'"
                fi
        fi
        _prevarg=""        
        return $_arg_cnt
}

:<<'EOF'
Framework callback for getting the default configuration file path if none is defined
in user space below .config/Sumo.
@param [1] A reference to the variable where the path shall be stored
EOF

Sumo__getDefaultConfigFile()
{
        local -n out_ConfileFilePath=$1
        out_ConfileFilePath="${SUMO__VARS["SUMO__MY_DIR"]}/sumo.yml"
        return 0
}

:<<'EOF'
Handles argument values not bound with any option
@param [1] rank of among all values not bound with any option
@param [2] actual arg value
@return 0 if accepted and handled, 1 otheriwse
EOF

Sumo__parseArgsHandleOptionLessArg() {
        local index=$1
        shift
        local value="$@"
        case ${__myarg_cnt} in
                0) SUMO__VARS["IMG_FILE"]="$value" ; return 0 ;; 
                1) SUMO__VARS["MOUNT_POINT"]="${value}" ; return 0  ;;
                *) return 1 ;;
        esac        
        return 1 # we should not reach this end
}

:<<'EOF'
Parse arguments callback which is called when _parseArgs is called.
Steps achieved:
1. It preprocess args to identify assigned option values of the form--x=Y and rebuilds them in order to split them into two arguments.
   It checks whether a value is required or not depending on SUMO__OPTION_LIST_ARGS[option]
2. It processes all args. 2 cases:
   The arg is an option. It evalutes SUMO__OPTION_LIST_ACTI[option] for the matching option (it may execute other code)
   The arg is not an option, i.e. either a plain arg or an option value. It calls Sumo__processDashLessArg for it.
3. There are further consistency checks depending on the specified arguments and the expected usage.
EOF

Sumo__parseArgs() {
        local argc=0
        local arg_cnt=0

        _log_dbg "Sumo__parseArgs"

        _parseFromArgToVars SUMO__OPTION_LIST_DESC SUMO__OPTION_LIST_ARGS SUMO__OPTION_LIST_ACTI SUMO__OPTION_LIST_VALS argc arg_cnt "$@"

        # If requesting another history, return immediately 
        # for processing the request and restart
        if [ ! -z "${SUMO__VARS["HISTORY_NAME"]}" ] ; then
                return 0
        fi

        _log_dbg "Sumo__parseArgs argc='$argc' arg_cnt='$arg_cnt'"

        # Interpret boolean values
        local configItem
        local configItemKey
        for configItemKey in "${!SUMO__VARS[@]}" 
        do 
                #_log_dbg "'$configItemKey': '${SUMO__VARS["$configItemKey"]}'"
                case "${SUMO__VARS["$configItemKey"]}" in
                        yes|YES|done|DONE) SUMO__VARS["$configItemKey"]=0 ;;
                        no|NO) SUMO__VARS["$configItemKey"]=-1 ;;
                        *) ;;
                esac
        done


        # If not called from another instance, initialize the logs
         if [ ! -v SUMO__VARS["CALLER"] ] ; then
                _initLogs
        else
                _initLogVars
        fi


       # Load explicit dependency specified to refresh
        if [ ! -z "${SUMO__VARS["REFRESH_DEPS"]}" ] ; then
                _log_dbg "REFRESH_DEPS "  
               if ! _loadDep "${SUMO__VARS["REFRESH_DEPS"]}" ; then
                        _exit -150 "Failed install dependency '${SUMO__VARS["REFRESH_DEPS"]}'. Aborted."
               fi
        fi
        
        #_quit ""
        if [ ! -z "${SUMO__VARS["REPLACE_IN_LIST"]}" ] ;  then
                local replaceString="${SUMO__VARS["REPLACE_IN_LIST"]}"
                SUMO__VARS["REPLACE_OLD_STRING"]="${replaceString%% *}" 
                SUMO__VARS["REPLACE_NEW_STRING"]="${replaceString##* }"
        fi


        #if [ ${SUMO__VARS["DO_UNMOUNT"]} -ne 0 ]  && [ -z "${SUMO__VARS["IMG_FILE"]}" ] && [ -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
        if [ $argc -eq 0 ] || ([ $arg_cnt -eq 0 ] && [ ${SUMO__VARS["DO_UNMOUNT"]} -ne 0 ] && [ -z "${SUMO__VARS["FS_LABEL"]}" ] ) ; then
                SUMO__CURRENT_OPERATION="list"
                Sumo__list
                if [ ${SUMO__VARS["NO_HEADER"]} -ne 0 ] ; then
                        _quit "" #Done. Use -l,--list for filtering with -L."
                else
                        _quit ""
                fi
        fi

        if [ ${SUMO__VARS["RUN_TESTS"]} -eq 0 ]; then
                return 0
        fi

        if [ ${SUMO__VARS["DO_UNMOUNT"]} -eq 0 ] ; then
                Sumo__parseArgsCheckConflictingUnmountInputArgs "For unmounting, specify only one among the following: a file, a mount point, a label or a block device."

                # When unmounting at least either a mount point, block device or a label must be specified.    
                if [ -z "${SUMO__VARS["IMG_FILE"]}" ] && [ -z "${SUMO__VARS["MOUNT_POINT"]}" ] &&  [ -z "${SUMO__VARS["FS_LABEL"]}" ] && [ ${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]} -ne 0 ] ; then
                        _susage "Invalid arguments. Unmounting requires any of the following: valid disk file path, mount mount, valid block device path or volume label."
                fi
        fi

        # This preliminary mount resolution was inserted to counter the case of an unmount attempt using
        # a mount point bound with a hanging connection. In that case, in findMountSource in Sumo__resolveBlockDeviceInfos
        # would block, as well as other -d, -e test done below
        # Update: additionally, it enables to set SUMO__VARS["IMG_DISK_FILE_PATH"]

        _log_dbg "parseargs file=${SUMO__VARS["IMG_FILE"]}"
        if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] ; then
                # Try to find mounting infos directly. 
                local mntSource=""
                local mntTarget=""
                local fullPath=""
                local isCloud=1
                local isUsb=1
                local logicalMntSource=""
                if Sumo__usb_isArgValidAddress "${SUMO__VARS["IMG_FILE"]}" ; then
                        fullPath="${SUMO__VARS["IMG_FILE"]}"
                        Sumo__usb_setConnectionsInfosFromFileURL "${SUMO__VARS["IMG_FILE"]}"
                        logicalMntSource="${SUMO__VARS["DEVPART"]}"
                        isUsb=0
                elif Sumo__network_isArgValidAddress "${SUMO__VARS["IMG_FILE"]}" ; then
                        fullPath="${SUMO__VARS["IMG_FILE"]}"
                        logicalMntSource="${fullPath}"
                elif Net__isHTTP "${SUMO__VARS["IMG_FILE"]}" && (host "${SUMO__VARS["IMG_FILE"]}" &>/dev/null) ; then
                #elif Sumo__cloud_isValidAddress ; then # && ping -c1 -w 2s "${SUMO__VARS["IMG_FILE"]}" &> /dev/null; then
                        isCloud=0
                        Sumo__cloud_setConnectionsInfosFromFileURL "${SUMO__VARS["IMG_FILE"]}"
                        fullPath="${SUMO__VARS["IMG_FILE"]}"
                        logicalMntSource="${SUMO__VARS["DEVPART"]}"
                else
                        fullPath="$(realpath -m -s "${SUMO__VARS["IMG_FILE"]}")"
                        logicalMntSource="${fullPath}"
                fi

                if [ -f "${SUMO__VARS["IMG_FILE"]}" ] ; then
                        #_log_dbg "parseargs is regular file OK=${SUMO__VARS["IMG_FILE"]}"
                        SUMO__VARS["IMG_DISK_FILE_PATH"]="${fullPath}"
                fi

                if Dev__findMount "$logicalMntSource" mntSource mntTarget ; then
                        _log_dbg "for logical mount source '$logicalMntSource', FOUND '$mntSource' '$mntTarget'"
                        if [ "$logicalMntSource" == "$mntTarget" ] ; then
                                SUMO__VARS["MOUNT_POINT"]="$mntTarget"
                                SUMO__VARS["IMG_FILE"]=""
                                Sumo__targetsListOfMyselfOwner+=("${SUMO__VARS["MOUNT_POINT"]}") # check if unmount with a source having multiple targets?
                                Sumo__devicesOftargetsListOfMyselfOwner+=("$mntSource")
                        fi
                        if [ $isCloud -eq 0 ] ||  [ $isUsb -eq 0 ]  ; then
                                # For clouds and usb, the mount source is forced 
                                # to the logical address if it is specified (source location)
                                SUMO__VARS["MOUNT_POINT_SOURCE"]="$fullPath"
                        else
                                SUMO__VARS["MOUNT_POINT_SOURCE"]="$mntSource"
                        fi
                        SUMO__VARS["MOUNTED"]=0
                fi
        fi

        # Is image file a folder for unmounting 
        if [ ${SUMO__VARS["DO_UNMOUNT"]} -eq 0 ] ; then
                # First argument shall be interpreted as the mount point if it is a directory
                if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] ; then
                        if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                                _susage "Too much arguments for unmounting." 
                        fi                

                        # This is to avoid potential hang-up related to network connections
                        if [ ! -z "${SUMO__VARS["MOUNT_POINT_SOURCE"]}" ] && Sumo__network_isArgValidAddress "${SUMO__VARS["MOUNT_POINT_SOURCE"]}" ; then 
                                # a valid mount was found above. Lets exit here
                                return 0
                        fi
                        if [ ! -z "${SUMO__VARS["MOUNT_POINT_SOURCE"]}" ] && Sumo__cloud_isArgValidAddress "${SUMO__VARS["MOUNT_POINT_SOURCE"]}" ; then 
                                # a valid mount was found above. Lets exit here
                                return 0
                        fi

                        if [ -d "${SUMO__VARS["IMG_FILE"]}" ] ; then
                                SUMO__VARS["MOUNT_POINT"]="${SUMO__VARS["IMG_FILE"]}"
                                SUMO__VARS["IMG_FILE"]=""
                        elif Str__contains "${SUMO__VARS["IMG_FILE"]}" ">" ; then
                                # This is an overlay unmount request
                                :
                        elif [ ! -e "${SUMO__VARS["IMG_FILE"]}" ] ; then
                                if Sumo__network_isArgValidAddress "${SUMO__VARS["IMG_FILE"]}" ; then
                                        :
                                elif Sumo__cloud_isArgValidAddress "${SUMO__VARS["IMG_FILE"]}"; then
                                        :
                                elif Sumo__usb_isArgValidAddress "${SUMO__VARS["IMG_FILE"]}"; then
                                        :
                                else
                                        # Test if network
                                        _susage "'${SUMO__VARS["IMG_FILE"]}' is an invalid argument: neither a device, nor a directory, nor a network URL."
                                        #_susage "${SUMO__VARS["IMG_FILE"]} does neither exist nor is a valid block device path."
                                fi
                        fi
                fi      
        # else is image file  a folder for mounting based on label ? 
        else
                # ALREADY COMMENTED BEFORE  INVALID
                #if [ ! -z "${SUMO__VARS["MOUNT_POINT_SOURCE"]}" ] ; then # a mount point was found
                #        _quit "${SUMO__VARS["IMG_FILE"]} is already mounted."
                #fi

                # First argument (img_file) shall be interpreted as the mount point if it is a directory and a label is specified
                # The  -d dir test  of the 'if' commented 14/05/25 to handle mounting with label
                # if validity of dir tested afterward, or its creation also managed afterwards
                if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] && [ ! -z "${SUMO__VARS["FS_LABEL"]}" ] ; then # && [ -d "${SUMO__VARS["IMG_FILE"]}" ] 
                        if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                                _susage "Too much arguments for mounting. Use only one among the following: device path, disk file, label."
                        fi

                        SUMO__VARS["MOUNT_POINT"]="${SUMO__VARS["IMG_FILE"]}"
                        SUMO__VARS["IMG_FILE"]=""
                        # If the file does not exist, it will be asked to create it.
                        # If the file does exist, it will be attempted to mount the disk inside
                fi      
        fi

        # Is image file a block device ?
        if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] && [ -e "${SUMO__VARS["IMG_FILE"]}" ] ; then
                #lsblk "${SUMO__VARS["IMG_FILE"]}" &>/dev/null                
                # Deal with symbol links like /dev/mapper/veracrypt1
                local assumedBlkDevPath="${SUMO__VARS["IMG_FILE"]}"
                if [ -h "$assumedBlkDevPath" ] ; then
                        assumedBlkDevPath=$(realpath "$assumedBlkDevPath")
                fi                
                local filetype=$(stat -c "%F" "$assumedBlkDevPath" 2>/dev/null)
                if Str__startsWith "$filetype" "block" ; then
                        SUMO__VARS["IMG_FILE_IS_BLK_DEV"]=0
                fi
        fi        

        # TODO STILL CORRECT? normally the FS label is used , not the vera slot number anymore
        if Sumo__isVera ; then
                # Only numeric label are supported in the meantime (see --slot)
                if [ ! -z "${SUMO__VARS["FS_LABEL"]}" ] && ! Int__isInt "${SUMO__VARS["FS_LABEL"]}" ; then
                        _susage "Invalid arguments. Labels must be integer values for Vera volumes."
                fi
        fi

        # Test listing arguments
        if [ ${SUMO__VARS["LIST"]} -eq 0 ] ; then
                _log_dbg "FILE for listing '${SUMO__VARS["IMG_FILE"]}' '${SUMO__VARS["MOUNT_POINT"]}'   "
                if [ ${SUMO__VARS["DO_UNMOUNT"]} -eq 0 ] ; then
                        _susage "Incompatible arguments -l and -u specified. Please either request unmounting or listing."
                fi
                if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                        _susage "Invalid arguments. It seems a useless mountpoint argument was defined for list command."
                fi                
                if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] && [ ${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]} -ne 0 ] ; then
                        _susage "Invalid arguments. Listing can only accept an actual block device path as argument."
                fi

                SUMO__CURRENT_OPERATION="list"
                Sumo__list

                if [ ${SUMO__VARS["NO_HEADER"]} -ne 0 ] ; then
                        _quit "" # Done. Use -l,--list for filtering with -L or -D."
                else
                        _quit ""
                fi
        fi

        # If unmount is used, the first argument gives either the device or the mount point.
        if [ ${SUMO__VARS["DO_UNMOUNT"]} -ne 0 ] ; then
                  # When mounting at least either a file/device or a label must be specified.
                 if [ -z "${SUMO__VARS["IMG_FILE"]}" ] &&  [ -z "${SUMO__VARS["FS_LABEL"]}" ] && [ ${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]} -ne 0 ] ; then
                        _susage "Mounting requires at least a disk file/device path or a volume label to be specified."
                 fi
        fi

        # For files, set the realpath and try to determine image type from the file extension
        if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] && [ ${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]} -ne 0 ] ; then
                
                _log_dbg "file: '${SUMO__VARS["IMG_FILE"]}'"
                if Sumo__network_isArgValidAddress "${SUMO__VARS["IMG_FILE"]}" || Sumo__cloud_isArgValidAddress "${SUMO__VARS["IMG_FILE"]}" ; then
                        :
                elif Sumo__usb_isArgValidAddress "${SUMO__VARS["IMG_FILE"]}" ; then
                        :
                elif [ ! -z "${SUMO__VARS["FS_LABEL"]}" ] ; then
                        # When mounting or unmount from a label, the below test should not be done
                        :
                elif Str__contains "${SUMO__VARS["IMG_FILE"]}" ">" ; then
                        #SUMO__VARS["LOWER_DIRS"]=""
                        local upperdir
                        local lowerdir
                        local remainlowerdir
                        local nbLowerDirs=0
                        Str__split "${SUMO__VARS["IMG_FILE"]}" upperdir ">" lowerdir 1
                        if [ ! -d "$upperdir" ] ; then _susage "Argument '${upperdir}' is not a valid directory for an overlay mount." ; fi                        
                        SUMO__VARS["IMG_FILE"]="$upperdir"
                        remainlowerdir="$lowerdir"
                        while Str__contains "${remainlowerdir}" ">" ; do
                                Str__split "$remainlowerdir" lowerdir ">"  remainlowerdir 1
                                echo "Hey ! $lowerdir -> $remainlowerdir"
                                if [ ! -d "$lowerdir" ] ; then _susage "Argument '${lowerdir}' is not a valid directory for an overlay mount." ; fi                        
                                nbLowerDirs=$(($nbLowerDirs + 1))
                                SUMO__VARS["LOWER_DIRS"]="${SUMO__VARS["LOWER_DIRS"]}:${lowerdir}"
                        done
                        if [ ! -d "$remainlowerdir" ] ; then _susage "Argument '${remainlowerdir}' is not a valid directory for an overlay mount." ; fi                        

                        # Added the remaining and cleaning up the heading ':' added in first iteration on multiple lower dir
                        nbLowerDirs=$(($nbLowerDirs + 1))
                        Str__trimStart "${SUMO__VARS["LOWER_DIRS"]}:${remainlowerdir}" lowerdir ":"
                        SUMO__VARS["LOWER_DIRS"]="$lowerdir"
                        SUMO__VARS["NB_LOWER_DIRS"]=$nbLowerDirs

                        _log_dbg "OVERLAY MOUNT: upperdir='${SUMO__VARS["IMG_FILE"]}' , lowerdirs='${SUMO__VARS["LOWER_DIRS"]}'"

                elif Net__isNFS "${SUMO__VARS["IMG_FILE"]}" || Net__isNFSURL "${SUMO__VARS["IMG_FILE"]}" ; then
                        #_log "=========> NFS!!! ${SUMO__VARS["IMG_FILE"]}"
                        :
                else
                        SUMO__VARS["IMG_FILE"]=$(realpath -m "${SUMO__VARS["IMG_FILE"]}")
                        local fileExt
                        File__ext "${SUMO__VARS["IMG_FILE"]}" fileExt
                        Str__toLower fileExt
                        #_log_dbg "disk file: '${SUMO__VARS["IMG_FILE"]}' , ext '$fileExt'"
                        if Array__contains_by_string "${SUMO__VARS["ALLIMAGETYPES"]}" "$fileExt" ; then
                                SUMO__VARS["IMG_TYPE"]="$fileExt"
                        else
                                if [ -z "$ext" ] ; then
                                        local extension=""
                                        if [ ! -z "$fileExt" ] ; then
                                                extension=" of extension '$fileExt'"
                                        fi
                                        _susage "Argument '${SUMO__VARS["IMG_FILE"]}'${extension} is either an invalid mount directory or the filename does not match any of the known image types : ${SUMO__VARS["ALLIMAGETYPES"]}"
                                else
                                        _susage "file extension '${ext}' does not match any of the known image types : ${SUMO__VARS["ALLIMAGETYPES"]}"
                                fi
                        fi
                fi
        fi

        # Added 16/7/2024 for device formatting
        if ${SUMO__VARS["FORMAT_DISK"]} ; then        
                if [ ${SUMO__VARS["DO_UNMOUNT"]} -eq 0 ] ; then
                        _susage "Option -F|--format-disk specified in unmount request."
                fi
                if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                        _susage "Option -F|--format-disk specified while a mount point is specified."
                fi
                if [ -z "${SUMO__VARS["FS_TYPE"]}" ] ; then
                        _susage "Option -t|--fs-type must be specified along with-F|--format-disk."
                fi
:<<'EOF'
#WHY?
                if [ -z "${SUMO__VARS["CALLER"]}" ] ; then
                         _susage "Option -F|--format-disk can be used only when called internally from the interative mode."
                fi
EOF
        fi

        # Added 4/8/2024 for flashing disk images
        if [ ! -z "${SUMO__VARS["FLASH_DISK"]}" ] ; then
                if [ ${SUMO__VARS["DO_UNMOUNT"]} -eq 0 ] ; then
                        _susage "Option -B|--flash-disk specified in unmount request."
                fi
                if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                        _susage "Option -B|--flash-disk specified while a mount point is specified."
                fi
                if [ ! -f "${SUMO__VARS["FLASH_DISK"]}"  ] ; then
                        _susage "${SUMO__VARS["FLASH_DISK"]} does not exist."
                fi
        fi

        return 0
}

:<<'EOF'
This argument checking routine is called by Sumo__parseArgs. It checks against arguments which may conflict with each other.
EOF

Sumo__parseArgsCheckConflictingUnmountInputArgs() {
        local multipleArgs=1
        #_log_dbg "values '${SUMO__VARS["MOUNT_POINT"]}' '${SUMO__VARS["FS_LABEL"]}' '${SUMO__VARS["IMG_FILE"]}' '${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]}'"
        if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] || [ ! -z "${SUMO__VARS["FS_LABEL"]}" ] || [ ${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]} -eq 0 ] ; then
                        multipleArgs=0
                fi
        fi
        if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] ; then
                # IMG_FILE may contain the device path
                if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] || [ ! -z "${SUMO__VARS["FS_LABEL"]}" ] ; then
                        multipleArgs=0
                fi
        fi
        if [ ! -z "${SUMO__VARS["FS_LABEL"]}" ] ; then
                if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] || [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] || [ ${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]} -eq 0 ] ; then
                        multipleArgs=0
                fi
        fi
        if [ ${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]} -eq 0 ] ; then
                # IMG_FILE contains the device path
                if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] ||  [ ! -z "${SUMO__VARS["FS_LABEL"]}" ]; then
                        multipleArgs=0
                fi
        fi
        if [ $multipleArgs -eq 0 ] ; then
                _susage "$1"
        fi
}

:<<'EOF'
Indicates whether the input given for mount/unmount was a disk file or not. 
This function shall be called only after the argument parsing using __parseArgs
@returns 0 when true, 1 otherwise
EOF

Sumo__isDiskFile() {
        if [ ! -z "${SUMO__VARS["IMG_DISK_FILE_PATH"]}" ] ;  then
                return 0
        fi

        if [ ! -z "${SUMO__VARS["NB_LOWER_DIRS"]}" ] ; then
                if [ "${SUMO__VARS["NB_LOWER_DIRS"]}" -ge 1 ] ; then
                        return 1
                fi
        fi

        # TODO CHECK not sure this is OK
        if [ ${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]} -ne 0 ] && [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] ;  then
                return 0
        fi
        
        return 1
}


:<<'EOF'

Main unmounting function.

On shutdown, all disks are unmounted
according to https://www.reddit.com/r/archlinux/comments/ahtaxf/encrypted_partitions_at_shutdown/
closing Luks is only a formality, since the data remains always encrypted on disk
The lo device is anyway also not permanent and gets lost between boots

EOF

Sumo__unmount() {
        SUMO__CURRENT_OPERATION="unmount"

        # Handle explicit unmounting
        # On shutdown, all disks are unmounted
        # according to https://www.reddit.com/r/archlinux/comments/ahtaxf/encrypted_partitions_at_shutdown/
        # closing Luks is only a formality, since the data remains always encrypted on disk
        # The lo device is anyway also not permanent and gets lost between boots
                
        local res=1
        if [ ${SUMO__VARS["MOUNTED"]} -eq 0 ] ; then
                if [ -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then 
                        Sumo__resolveMountingInfos "${SUMO__VARS["DEVPART"]}"
                fi

                _log_dbg "Sumo__unmount: mountpoint found '${SUMO__VARS["MOUNT_POINT"]}', DEVMAPPER='${SUMO__VARS["DEVMAPPER"]}'"

                Sumo__unmountChilds

                local ret=0
                if Sumo__isVera ; then
                        Sumo__vera_unmount
                        ret=$?
                else
                        if [ ! -v SUMO__VARS["ALL_FLAG"] ] && [ ${#Sumo__targetsListOfMyselfOwner[@]} -gt 1 ] ; then
                                # This case should not happen, because it should have exited before while founding 
                                # the multiple mountpoints
                                _exit -1 "internal error - SUMO__VARS["ALL_FLAG"] not set and multiple mount points detected"
                        fi

                        local targetcnt=0
                        local mountpoint
                        local deviceTarget
                        local nbUnmountOK=0
                        while [ $targetcnt -lt ${#Sumo__targetsListOfMyselfOwner[@]} ] ;
                        do
                                mountpoint="${Sumo__targetsListOfMyselfOwner[$targetcnt]}"
                                deviceTarget="${Sumo__devicesOftargetsListOfMyselfOwner[$targetcnt]}"
                                local lazyOpt=""
                                if [ "${SUMO__VARS["LAZY"]}" == "lazy" ] ; then lazyOpt="-l -f" ; fi
                                local cmd="${__SUDO__}umount ${lazyOpt} \"$mountpoint\""
                                _logf "UMOUNT COMMAND: '$cmd'"
                                eval "$cmd" 2>&1 #| tee -a "${__LOG_FILE__}" # with the umount error are masked!
                                if [ $? -ne 0 ] ; then 
                                        _log_warn -1 "Failed to unmount '$mountpoint'"
                                        ret=-1
                                else
                                        Sumo__updateSavedRecentList "${deviceTarget}" "$mountpoint" "${SUMO__VARS["IMG_DISK_FILE_PATH"]}" "unmount"

                                        if Sumo__isVirt ; then
                                                # NO: DONT DO THAT qemu --disconnect shall be called only on /dev/ndb0 device, not /dev/nb0p1, p2 etc
                                                # 
                                                #Sumo__virt_nbd_close "${deviceTarget}"
                                                if [ $? -ne 0 ] ; then
                                                        _log_warn "Failed to clean up NBD device '${deviceTarget}'"
                                                fi
                                        fi

                                        _log "Successfully unmounted $mountpoint from ${deviceTarget}"
                                        nbUnmountOK=$(($nbUnmountOK + 1))
                                        if rmdir "$mountpoint" 2>/dev/null; then 
                                                if [ -z "${SUMO__VARS["SILENT"]}" ] ; then 
                                                        _log_dbg "Successfully removed the created mount folder '$mountpoint'."
                                                fi
                                        else
                                                _log_warn "Created mount folder '$mountpoint' was not removed, either no permission or folder is not empty. Please check and cleanup if necessary."
                                        fi
                                        _log_dbg "unmount DEV='${SUMO__VARS["DEV"]}' devpart:${deviceTarget} , devpart type:${SUMO__VARS["DEVPART_TYPE"]}, devmapper:${SUMO__VARS["DEVMAPPER"]}, FSTYPE=${SUMO__VARS["FS_TYPE"]}, BLKTYPE=${SUMO__VARS["BLK_TYPE"]}," 
                                        if Sumo__isLuks || [ "${SUMO__VARS["DEVPART_TYPE"]}" == "crypt" ]; then
                                                local FS_LABEL_USED_AT_OPENING="$(basename "${SUMO__VARS["DEVMAPPER"]}")" # This is actually correct

                                                _log_dbg "block device 'crypt' detected. FS_LABEL='${SUMO__VARS["FS_LABEL"]}' device mapper='${SUMO__VARS["DEVMAPPER"]}' "
                                                _log_dbg "FS_LABEL_USED_AT_OPENING=${FS_LABEL_USED_AT_OPENING}"
                                                # It happened that cryptsetup isLuks returns 1 (error) even for valid luks devices
                                                #if ${__SUDO__}cryptsetup isLuks "${deviceTarget}" >/dev/null; then
                                                _log_dbg "LUKS device ${deviceTarget} is luks detected. Volume=${FS_LABEL_USED_AT_OPENING}."
                                                if Sumo__luks_close "${SUMO__VARS["DEVMAPPER"]}" "${FS_LABEL_USED_AT_OPENING}" ; then
                                                        _log "Successfully closed LUKS volume ${FS_LABEL_USED_AT_OPENING} (device ${deviceTarget})."
                                                else 
                                                        _log_warn "Failed to close properly LUKS volume ${FS_LABEL_USED_AT_OPENING} (device ${deviceTarget})."
                                                fi
                                                #fi
                                        fi
                                fi
                                targetcnt=$(($targetcnt + 1))
                        done      
                        if [ $nbUnmountOK -eq ${#Sumo__targetsListOfMyselfOwner[@]} ] ; then
                                if  Sumo__isDiskFile;  then
                                        _log_dbg "Sumo__updateSavedRecentList for disk file"
                                        # The correct mountpoint for the disk file should have been saved in recent list at mount time
                                        # it may not be known at this point, since MOUNT_POINT may point to a child device after mount infos resolving
                                        # However, in any case, we put a best guess here
                                        local diskFileCorename
                                        File__corename "${SUMO__VARS["IMG_DISK_FILE_PATH"]}" diskFileCorename
                                        local defaultMountpoint
                                        defaultMountpoint="$(dirname "${SUMO__VARS["MOUNT_POINT"]}")/${diskFileCorename}"
                                        Sumo__updateSavedRecentList "${SUMO__VARS["IMG_DISK_FILE_PATH"]}"  "${defaultMountpoint}" "${SUMO__VARS["IMG_DISK_FILE_PATH"]}" "mount"
                                fi
                        fi
                fi                
:<<'EOF'
See cleanup
                if [ $ret -eq 0 ] ; then
                        if Dev__deactivateAllVolumeGroupsForDisk "${SUMO__VARS["DEV"]}" ; then
                                _log "Successfully removed volume groups for ${SUMO__VARS["DEV"]}"
                                if Sumo__isDiskFile ; then
                                        if Sumo__isVirt ; then
                                                Sumo__virt_nbd_close "${SUMO__VARS["DEV"]}"
                                        fi
                                fi
                        fi
                fi
EOF
                _exit $ret "" # Let _cleanup remove any loop device, do not use _quit
        else
                if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                        _quit "Nothing done: ${SUMO__VARS["MOUNT_POINT"]} is not mounted."
                else
                        if [ ! -z "${SUMO__VARS["FS_LABEL"]}" ]; then
                                _quit "No device found with label '${SUMO__VARS["FS_LABEL"]}'."
                        elif [ "${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]}" -eq 0 ] ; then
                                if ! Sumo__unmountChilds ; then
                                        _quit "Block device ${SUMO__VARS["IMG_FILE"]} is not mounted."
                                else
                                        _quit "Partition(s) part of block device ${SUMO__VARS["IMG_FILE"]} have been unmounted with success."
                                fi
                        else
                                _quit "There was no matching device found to be unmounted."
                        fi
                fi
        fi
}

:<<'EOF'
Unmounts of all devices which are childs of the devive stored in SUMO__VARS["DEVMAPPER"], resp. SUMO__VARS["DEVPART"].
Unmounting invokes anew the script for each of the childs.
As another major input, it resolves the device hierarchy using the AWK script sumo__seekchilds.awk, itself taking as input
the device ancestry reconstructed by function 'getDeviceAncestry' and 'getNetworkDeviceAncestry'.
EOF

Sumo__unmountChilds()
{
        _log_dbg "Sumo__unmountChilds: DEVMAPPER=${SUMO__VARS["DEVMAPPER"]} mountpoint='${SUMO__VARS["MOUNT_POINT"]}'"
        local fullAncestry="$(getDeviceAncestry)
$(getNetworkDeviceAncestry)"

        local ghostOpt=""
        if ${SUMO__VARS["HISTORY_GHOST"]} ; then ghostOpt="--ghost" ; fi

        local childs
        local device
        device="${SUMO__VARS["DEVMAPPER"]}"
        if [ -z "${device}" ] ; then
                device="${SUMO__VARS["DEVPART"]}"
        fi

        childs="$(echo ""|
        awk -v ancestry="$fullAncestry" \
        -v param_ancestor="${device}" \
        -v param_ancestor_mntp="${SUMO__VARS["MOUNT_POINT"]}" \
        -v LOG_DEBUG="${__LOG_DEBUG__}" \
        -i "${SUMO__VARS["SUMO__MY_DIR"]}/awk-api/awk-api-core.awk" \
        -i "${SUMO__VARS["SUMO__MY_DIR"]}/awk-api/awk-api-dev.awk" \
        -i "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__lib.awk" \
        -f "${SUMO__VARS["SUMO__MY_DIR"]}/sumo__seekchilds.awk" | \
        sort -nr | uniq) "
        _log_dbg "CHILD: '$childs'"
        #_log_dbg "fullAncestry: '$fullAncestry'"
        #_log_dbg "netScanAncestry: '$netScanAncestry'"

        Str__trimOnce "$childs" childs 
        local nbActualChild=0
        if [ ! -z "$childs" ] ; then
                # This first loop is for display purposes
                #
                #if [ -z "${SUMO__VARS["SILENT"]}" ] ; then 
                local firstChildMeet=1
                local childLine
                while IFS= read -r childLine
                do 
                        local trimmedChildLine
                        Str__trimOnce "$childLine" trimmedChildLine
                        if ! Str__startsWith "$trimmedChildLine" '\|' ;  then 
                                SUMO__VARS["IMG_DISK_FILE_PATH"]="$trimmedChildLine" ; 
                                continue 
                        fi
                        if [ -z "$trimmedChildLine" ] ; then continue ; fi
                        if [ $firstChildMeet -ne 0 ] ; then
                                firstChildMeet=0
                                _log "The device to unmount contains itself the following mounted volumes inside it":
                                _log ""
                        fi

                        local childData=()
                        readarray -t -d'|' childData <<< "$childLine"
                        local childDev="${childData[2]}"
                        local childFile="${childData[3]}"
                        local childMnt="${childData[4]}"
                        Str__trimOnce "$childDev" childDev 
                        Str__trimOnce "$childFile" childFile 
                        Str__trimOnce "$childMnt" childMnt 
                        # When using § there are strange chars  #Str__trim "$childDev" childDev $'\247'  #Str__trim "$childDev" childDev $'\302' # Clarify why this char? #Str__trim "$childMnt" childMnt $'\247' #Str__trim "$childDev" childDev §
                        if [ ! -z "$childFile" ] ; then
                                _log "Disk $childFile with respect to mount point $childMnt"
                        else
                                _log "$childDev mounted on $childMnt"
                        fi

                        nbActualChild=$(($nbActualChild + 1))                                                
                done <<< "$childs"
                _log ""

                #fi
                if [ $nbActualChild -gt 0 ] ; then
                        local doUnmount=0
                        if [ ! -v SUMO__VARS["FORCED"] ] ; then
                                local forcedInput
                                Input__getForcedInput forcedInput
                                if [ "$forcedInput" == "y" ] ; then
                                        Input__popForcedInput
                                fi

                                Input__confirm "The above contained volumes and disk files will be unmounted first as well. Proceed?"
                                doUnmount=$?
                                _log ""
                                if [ $doUnmount -ne 0 ] ; then
                                        _exit -1 "Aborted."
                                else
                                        if [ -z "${SUMO__VARS["SILENT"]}" ] ; then 
                                                printf "Yes. Proceeding now.\n\n"
                                        fi
                                fi
                                if [ "$forcedInput" == "y" ] ; then
                                        Input__pushForcedInput "$forcedInput" 
                                fi

                        fi
                        # This second loop is for launching the actual unmounting
                        declare -A childUnmountCommands
                        local anyUnmountFailure=1
                        while IFS= read -r childLine
                        do 
                                Str__trimOnce "$childLine" trimmedChildLine
                                if ! Str__startsWith "$trimmedChildLine" '\|' ;  then 
                                        continue 
                                fi

                                local childData=()
                                readarray -t -d'|' childData <<< "$childLine"
                                local childDev="${childData[2]}"
                                local childFile="${childData[3]}"
                                local childMnt="${childData[4]}"
                                Str__trimOnce "$childDev" childDev 
                                Str__trimOnce "$childFile" childFile 
                                Str__trimOnce "$childMnt" childMnt 
                                
                                local callerOpt=""
                                if [ ! -z "${SUMO__VARS["CALLER"]}" ] ; then
                                        callerOpt="--caller=0"
                                fi

                                local cmd
                                if [ -z "$childFile" ] ; then
                                        cmd="$0 ${ghostOpt} -s -y $callerOpt -u \"$childMnt\""
                                else
                                        cmd="$0 ${ghostOpt} -s -y -a $callerOpt -u \"$childFile\""
                                fi
                                local failure=1
                                if [ -z "${childUnmountCommands["$cmd"]}" ] ; then

                                        eval "$cmd"
                                        _logf "unmounting child COMMAND: $cmd"
                                        if [ $? -ne 0 ] ; then
                                                anyUnmountFailure=0               
                                        fi
                                        childUnmountCommands["$cmd"]="done"
                                fi
                        done <<< "$childs"
                        if [ $anyUnmountFailure -eq 0 ] ; then
                                _exit -1 "" #Failed to unmount $childDev."
                        fi

                        return 0
                else # nbActualChild test
                        return 1
                fi
        else
                return 1 # no child
        fi
}


:<<'EOF'
Call back function used when searching for a unique mount point path. It is called
by Sumo__manageValidMountpointSetting for setting the default proposed mount point.
If it already exists (and mounted from something else), this callback is called to 
propose an new path based on an incrementing counter which is passed on as argument.

@param [1] Counter for setting a unique mount point path
@param [2] output proposed mount point path
EOF

Sumo__getMountpoint()
{
        _log_dbg "Sumo__getMountpoint $1 $2"
        local cnt=$1
        local -n out_default_mp=$2

        if [ $cnt -eq 0 ] ; then
                mntp_suffix=""
        else
                mntp_suffix=":${cnt}"
        fi

        if [ ! -z "${SUMO__VARS["FS_LABEL"]}" ] ; then
                out_default_mp="${SUMO__VARS["FS_LABEL"]}${mntp_suffix}"
                return 0        
        else
                if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ]  ; then
                        if [ "${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]}" -eq 0 ] ; then
                                local label
                                Dev__getBlockDeviceLabel "${SUMO__VARS["IMG_FILE"]}" label
                                if [ ! -z "$label" ] ; then
                                        if [ -z "${SUMO__VARS["SILENT"]}" ] ; then 
                                                _log "Device label is '$label'"
                                        fi
                                        out_default_mp="$label${mntp_suffix}"
                                else
                                        local corename
                                        File__corename "${SUMO__VARS["IMG_FILE"]}" corename
                                        out_default_mp="${corename}${mntp_suffix}"
                                        #_log "this is my dflt: $out_default_mp"
                                fi
                        else
                                out_default_mp="$(Str__head "${SUMO__VARS["IMG_FILE"]}" "." last)${mntp_suffix}"
                        fi
                        #_log_dbg "Sumo__getMountpoint out_default_mp=${out_default_mp}"

                        return 0     
                else # file empty?
                        : # TODO CHECK 
                fi

                return 1
        fi
}

:<<EOF
This function is in charge of ensuring that a valid mountpoint is set when mounting. 
Either an explicit path is passed on to this function or the function attempts to define a default one via 
the call back given as first argument. Typically, the callback is Sumo__getMountpoint for block devices and
Sumo__network_getMountpoint for network connections.

In both cases, it checks whether the path is not yet mounted and when so , attempts to propose an alternative
path, which bases on a counter which is added as ':<counter>' to the mountpoint path.

In both cases, when a valid mountpoint is found, a proposal confirmation is submitted to the user (except if the -y 
option is specified).

When finally a valid mountpoint is confirmed, Sumo__setMountPoint is called.

@param [1] call back to get a mount point path according to a passed counter.
@param [2] optional, an explicit mountpoint
EOF

Sumo__manageValidMountpointSetting()
{
        _log_dbg "Sumo__manageValidMountpointSetting $# args '$1' '$2'"
        local callback_fn=$1
        local default_mp=""
        local mountpoint=""
        local cnt=0
        local proposedMountpointConfirmed=1
        local proposedMountpoint=""
        local doConfirmNewEnteredMountpoint=1

        if [ $# -eq 2 ]; then 
                proposedMountpoint="$2"
                if [ ! -e "$proposedMountpoint" ] ; then
                        Input__confirm "Folder '$proposedMountpoint' does not exist. Do you want to create it?"                                
                        if [ $? -eq 0 ] ; then
                                _log ""
                                SUMO__VARS["MOUNT_POINT"]="" # This will force creation of the folder from  Sumo__setMountPoint                                               
                                # mountpoint contains a valid new folder math. setMountPoint() will be called at the end of this function
                                proposedMountpointConfirmed=0
                        else
                                _log ""
                                _exit -1 "Aborted."
                        fi
                elif [ ! -d "${SUMO__VARS["MOUNT_POINT"]}"  ] ; then
                        _susage "The mount point '$mountpoint' is not a valid directory."

                else
                        proposedMountpointConfirmed=0
                        # else mountpoint contains a valid folder path
                        # setMountPoint() will be called at the end of this function
                fi
        fi

        if [ $proposedMountpointConfirmed -ne 0 ] || [ -z "$proposedMountpoint" ]; then
                if ! eval "$callback_fn $cnt default_mp" ; then
                        _exit -22 "Internal error - failure encountered while invoking callback function $callback_fn with counter $cnt"
                fi
                mountpoint="$default_mp"
        # else , the mount point is the one given by second function argument and was confirmed above 
        else
                mountpoint="$proposedMountpoint"
        fi

        _log_dbg "Sumo__manageValidMountpointSetting: mountpoint=$mountpoint proposed=$proposedMountpoint"

        while [ 0 -eq 0 ] 
        do
                #echo "MOUNT_POINT: '${SUMO__VARS["MOUNT_POINT"]}' doConfirmNewEnteredMountpoint: ${doConfirmNewEnteredMountpoint}"
                if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                        #_log_dbg "MOUNT_POINT nbtarget=${#Sumo__targetsListOfMyselfOwner[@]}" 
                        #_log_dbg "mountpoint: '$(realpath -m "${mountpoint}")' callback='$callback_fn'"
                        local target=""
                        local exists=1
                        for target in "${Sumo__targetsListOfMyselfOwner[@]}" ; do
                                #_log_dbg "target: '$(realpath -m "${target}")'"
                                local mymntp="$(realpath -m -s "${mountpoint}")"
                                local targetmntp="$(realpath -m -s "${target}")"
                                # It must be checked that the new mountpoint is not below an existing target
                                
                                #if Str__startsWith "$mymntp" "$targetmntp" ; then
                                if [ "$mymntp" == "$targetmntp" ] ; then
                                        if [ $doConfirmNewEnteredMountpoint -eq 0 ] ; then
                                                _log_err "The entered folder matches an already mounted target"
                                        fi
                                        exists=0
                                        break;
                                elif Str__startsWith "$(dirname "$mymntp")" "$targetmntp" ; then
                                        if [ $doConfirmNewEnteredMountpoint -eq 0 ] ; then
                                                _log_err "The entered folder is located below the already mounted target '$targetmntp'"
                                        fi
                                        exists=0
                                        break;
                                fi
                        done

                        if [ $exists -eq 0 ] ; then
                                if [ $doConfirmNewEnteredMountpoint -eq 0 ] ; then # Last entered was not confirmed, retry with previous default
                                        doConfirmNewEnteredMountpoint=1
                                        cnt=$(( $cnt - 1))
                                else                                        
                                        cnt=$(( $cnt + 1))
                                        if ! eval "$callback_fn $cnt default_mp" ; then
                                                _exit -22 "Internal error - failure encountered while invoking callback function $callback_fn with counter $cnt"
                                        fi                                
                                        mountpoint="$default_mp"
                                fi
                                continue
                        fi
                fi

                if [ $doConfirmNewEnteredMountpoint -eq 0 ] ; then
                        # Check if mount point not mounted elsewhere from another device
                        local realPathEnteredMntp
                        realPathEnteredMntp="$(realpath -e -s "$mountpoint" 2>/dev/null)"
                        if [ $? -eq 0 ] ; then
                                # If the mount target dir exists, lets check for the mounting status
                                if findmnt -n --mountpoint "${realPathEnteredMntp}" &> /dev/null; then
                                        # Initially, only doConfirmNewEnteredMountpoint was set to 1
                                        # which could result in infinite loop in cases were
                                        # MOUNT_POINT is empty.
                                        #doConfirmNewEnteredMountpoint=1 
                                        #continue
                                        _log_warn "'$(realpath "$mountpoint")' is already taken and mounted."
                                        cnt=$(( $cnt + 1))
                                        if ! eval "$callback_fn $cnt default_mp" ; then
                                                _exit -22 "Internal error - failure encountered while invoking callback function $callback_fn with counter $cnt"
                                        fi                                
                                        mountpoint="$default_mp"
                                else
                                        break # confirm ok
                                fi
                        else
                                # If the mount target dir does not exist all is fine.
                                break # confirm ok
                        fi
                fi      

                if [ $proposedMountpointConfirmed -eq 0 ] && [ $cnt -eq 0 ] ; then
                         # initial proposal is OK
                        break;
                else
                        local prompMount="Enter mount point"
                        if [ ! -d "$(realpath -m -s "$default_mp")" ] ; then
                                prompMount="$prompMount (folder is created if necessary)"
                        fi                     
                        # After input, we know the path which was entered is either an existing dir
                        # or one to create                   
                        if ! Input__dirpath "$prompMount" "${default_mp}" 2 mountpoint ; then
                                _exit -1 "Aborted."
                        else
                                if [ "$mountpoint" == "${default_mp}"  ] ; then
                                        break
                                else
                                        doConfirmNewEnteredMountpoint=0
                                fi
                        fi
                fi
        done
        _log_dbg "managed mntp: '$mountpoint'" 

        # Create the defined mount point folder
        if [ ! -e "$mountpoint" ] ; then 
                mkdir -p "$mountpoint" &>/dev/null 
                SUMO__VARS["MOUNT_POINT_CREATED"]=0
        fi

        local mount_announcement # obsolete to be removed
        Sumo__setMountPoint "$mountpoint" mount_announcement
}

:<<EOF
Sets the mount point for the mount operation to the passed value, if not defined yet.
Performs some correctness checks (existing? directory?) and creates
the folder if it does not exist.
EOF

Sumo__setMountPoint()
{
        local themountpoint="$1"
        local -n _mountannouncement=$2
        local doLog=$3
        local install_cmd=""
        local filePermMask="${SUMO__VARS["SECURITY_MASK"]}" # "$(umask)"
        
#        if [ -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                if [ ! -z "$doLog" ] ; then
                        _log "Assuming mount folder '$(realpath -m "$themountpoint")'."
                fi

                if [ -d "${themountpoint}" ] ; then
                        _mountannouncement="Mounting folder $(realpath -m "${themountpoint}")."
                        install_cmd="$(printf "${__SUDO__}install -d -o $(id -u) -g $(id -g) -m %o \"${themountpoint}\"" $((0777 & ~$filePermMask)))"
                        _logf "INSTALL COMMAND (Sumo__setMountPoint for existing dir): ${install_cmd}"
                        eval "${install_cmd}" 2>&1 #| tee -a "${__LOG_FILE__}"
                elif [ -e "${themountpoint}" ] ; then
                        _susage "the mount target '${themountpoint}' is invalid: the file exists, but it is not a directory."
                        :
                else
                        #_log_dbg "USER: $USER, id -u : $(id -u)"
                        install_cmd=$(printf "${__SUDO__}install -d -o $(id -u) -g $(id -g) -m %o \"${themountpoint}\"" $((0777 & ~$filePermMask)))
                        _logf "INSTALL COMMAND (Sumo__setMountPoint): ${install_cmd}"
                        eval "${install_cmd}" 2>&1 #| tee -a "${__LOG_FILE__}"
                        while [ $? -ne 0 ] ; do # mkdir -p "${themountpoint}" &> /dev/null ; do
                                Input__popForcedInput # Force manual entry
                                local prompMount="Failed to create mount directory. Please enter another mount point"
                                local themountpoint="$HOME/$(basename "${themountpoint}")"
                                if ! Input__dirpath "$prompMount" "${themountpoint}" 1 themountpoint ; then
                                        _exit -1 "Aborted."
                                fi
                                install_cmd=$(printf "${__SUDO__}install -d -o $(id -u) -g $(id -g) -m %o \"${themountpoint}\"" $((0777 & ~$filePermMask)))
                                _logf "INSTALL COMMAND (Sumo__setMountPoint): ${install_cmd}"
                                eval "${install_cmd}" 2>&1 #| tee -a "${__LOG_FILE__}"
                        done
                        _mountannouncement="Mounting newly created folder $(realpath -m "${themountpoint}")..."
                        SUMO__VARS["MOUNT_POINT_CREATED"]=0
                fi

                SUMO__VARS["MOUNT_POINT"]="${themountpoint}"
:<<'EOF'
        else
                if [ ${SUMO__VARS["MOUNTED"]} -eq 0 ] ; then
                        while [ 0 -eq 0 ] 
                        do
                                if [ "$(realpath -m "${themountpoint}")" != "$(realpath -m "${SUMO__VARS["MOUNT_POINT"]}")" ] ; then
                                        break
                                fi
                                Input__popForcedInput  # Force manual entry
                                local prompMount="Device is already mounted on ${SUMO__VARS["MOUNT_POINT"]}. Please choose another mount point"
                                local themountpoint=""
                                if ! Input__dirpath "$prompMount" "${themountpoint}" 1 themountpoint ; then
                                        _exit -1 "Aborted."
                                fi
                        done
                        _mountannouncement="Mounting newly created folder $(realpath -m "${themountpoint}")..."
                        SUMO__VARS["MOUNT_POINT_CREATED"]=0
                        SUMO__VARS["MOUNT_POINT"]="${themountpoint}"
                else
                        _mountannouncement="Attempting to mount folder $(realpath -m "${themountpoint}")"
                fi
        fi
EOF

        # In all cases, either if MOUNT_POINT was already defined before this function or 
        # by this function, we check the folder validity
        if [ ! -d "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                _susage "invalid target mount directory '${themountpoint}' specified."
        fi

}

:<<'EOF'
This function is in charge of managing the creation of disk files.
Disk file of name given by SUMO__VARS["IMG_FILE"] is created with 'dd' too according to the requested size given by option SUMO__CREATION_OPTIONS[size].
If no size was defined by option, the user is prompted to enter one.

sgdisk is called upon SUMO__VARS["IMG_FILE"] to create and format a single Linux partition on the disk (type 8300)

EOF

Sumo_createDiskFile()
{
        #SUMO__VARS["IMG_FILE"]="${SUMO__VARS["IMG_FILE"]}" # The following does not work if a relative path is given: SUMO__VARS["IMG_FILE"]="$(File__corename "${SUMO__VARS["IMG_FILE"]}").${SUMO__VARS["IMG_TYPE"]}"
        _log "The created file will have the ${SUMO__VARS["IMG_TYPE"]} extension."
        if Sumo__isLuks ; then
                _log "Please note LUKS images must be at least 32Mib to store meta data."
        fi

        local memsize=0
        local memunit=""

        Input__pushForcedInput "${SUMO__CREATION_OPTIONS[size]}"
        Input__memsize "Please enter disk size" memsize memunit
        if [ $? -ne 0 ] ; then
                _exit -1 "Aborted disk creation."
        fi

        _log "Creating disk image ${SUMO__VARS["IMG_FILE"]}, of size $memsize bytes with blocks of 512 bytes"
        if Dev__createRawDiskImage "${SUMO__VARS["IMG_FILE"]}" $memsize ${SUMO__VARS["BLOCK_SIZE"]} ; then
                _log "Disk file ${SUMO__VARS["IMG_FILE"]} was successfully created."
                Dev__createSinglePartition "${SUMO__VARS["IMG_FILE"]}" "${SUMO__VARS["FS_TYPE"]}" 1
                return $?
        else
                return 1
        fi

}

:<<'EOF'
This function is in charge of flashing a disk
@param[1] disk image
@param[2] device
You can check here how to build a bootable iso image
https://github.com/torvalds/linux/blob/64291f7db5bd8150a74ad2036f1037e6a0428df2/arch/x86/boot/Makefile#L177
EOF

Sumo__flashDisk()
{        
        if ! Args__checkCount ${FUNCNAME[0]} 2 "$#" "Usage: <disk image file> <device>"; then return 1; fi

        local __disk="$1"
        local __device="$2"

        if [ "${SUMO__VARS["MOUNTED"]}" -eq 0 ] ; then
                _exit -1 "${SUMO__VARS["IMG_FILE"]} is currently mounted."
        fi

        if [ "${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]}" -ne 0 ] ; then
                _exit -1 "${SUMO__VARS["IMG_FILE"]} not a block device."
        fi

        if [ ! -f "${SUMO__VARS["FLASH_DISK"]}"  ] ; then
                _susage "${SUMO__VARS["FLASH_DISK"]} does not exist."
        fi

        _logf "flashing disk: disk: '${__disk}' device: '${SUMO__VARS["IMG_FILE"]}'"

        if Input__confirm "All data on '${SUMO__VARS["IMG_FILE"]}' will get lost. Flash '${SUMO__VARS["FLASH_DISK"]}' on that device?" ; then
                echo
                _log "The operation will now be started. It may last up to several few minutes."
                echo
                local cmd
                cmd="${__SUDO__}dd if='${SUMO__VARS["FLASH_DISK"]}' of='${SUMO__VARS["IMG_FILE"]}' status=progress bs=16M"
                _logf "COMMAND: $cmd" 

                eval "$cmd" 2>&1 #| tee -a "${__LOG_FILE__}"
        else
                _log "Aborted."
                return 1
        fi
}

:<<'EOF'
This function is in charge of partitioning a disk
@param[1] partition type UUID
@param[2] device
EOF

Sumo__partDisk()
{        
        if ! Args__checkCount ${FUNCNAME[0]} 2 "$#" "Usage: <disk image file> <device>"; then return 1; fi

        local __uuid="$1"
        local __device="$2"

        if [ "${SUMO__VARS["MOUNTED"]}" -eq 0 ] ; then
                _exit -1 "${SUMO__VARS["IMG_FILE"]} is currently mounted."
        fi

        if [ "${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]}" -ne 0 ] ; then
                _exit -1 "${SUMO__VARS["IMG_FILE"]} not a block device."
        fi

        _logf "Creating partition of type '${Dev__PartitionTypes["${__uuid}"]}' , UUID='${__uuid}', on device: '${SUMO__VARS["IMG_FILE"]}'"

        if Input__confirm "All data on '${SUMO__VARS["IMG_FILE"]}' will get lost. Create partition of type '${Dev__PartitionTypes["${__uuid}"]}', UUID='${__uuid}' on that device?" ; then
                echo
                _log "The operation will now be started. It may last some time."
                echo
                Dev__createSinglePartitionDirect "${__device}" "${__uuid}"  0
        else
                _log "Aborted."
                return 1
        fi
}

:<<'EOF'
This function is in charge of formatting of a disk
@param[1] filesystem name
@param[2] passphrase
EOF

Sumo__formatDisk()
{        
        if ! Args__checkMinCount ${FUNCNAME[0]} 1 "$#" "Usage: <file system id> [<passphrase>]"; then return 1; fi

        local __fstype="$1"
        local __original_fstype="$1"
        local passphrase="$2"

        # Test if not mounted
        # But since this can be called only from the interactive console, the following
        # test should be deemed to be useless
        # - the device or any item below should have been unmounted beforehand
        # - the device is a block device. LIMITATION: DISK FILES CANNOT BE FORMATTED
        if [ "${SUMO__VARS["MOUNTED"]}" -eq 0 ] ; then
                _exit -1 "${SUMO__VARS["IMG_FILE"]} is currently mounted."
        fi
        if [ "${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]}" -ne 0 ] ; then
                _exit -1 "${SUMO__VARS["IMG_FILE"]} not a block device."
        fi

        _logf "Format disk: FS_TYPE: '${__fstype}' IMG_FILE: '${SUMO__VARS["IMG_FILE"]}' DEV:'${SUMO__VARS["DEV"]}' FS_LABEL:'${SUMO__VARS["FS_LABEL"]}'"

        local actualDeviceToFormat=""
        if [ ! -z "${SUMO__VARS["DEV"]}" ] ; then
                actualDeviceToFormat="${SUMO__VARS["DEV"]}"
        else
                actualDeviceToFormat="${SUMO__VARS["IMG_FILE"]}"
        fi
                cat <<EOF
You're going to be ask whether to create a partitionless device. Please note :
  - A partitionless device misses a MDR/GPT sector and can not be partitioned later
  - A partitionless device may not be recognized by some systems and devices
  - It may not be allowed for some systems, like FAT family (FAT32, exfat,vfat etc.)
However:
  - It may be recommended if anyway whole device is needed and going to be used (e.g. as backup)
  - You don't have to worry about limitations of the partition format (e.g. max size of a part)

If partitionless is not selected, a single partition taking the whole disk space will be created.  

ALL DATA ARE GOING TO BE LOST on ${SUMO__VARS["IMG_FILE"]}${SUMO__VARS["DEV"]}, label:'${SUMO__VARS["FS_LABEL"]}'
EOF
        # refs:
        #https://unix.stackexchange.com/questions/346826/is-it-ok-to-mkfs-without-partition-number  
        #https://unix.stackexchange.com/questions/14010/the-merits-of-a-partitionless-filesystem              

        local partLess=1
        local actualDeviceForHostingFilesystem=""
        Input__confirm "Would you like to create a partitionless device on '${actualDeviceToFormat}'?"
        partLess=$?
        _log ""
        if [ $partLess -eq 0 ] ; then
                actualDeviceForHostingFilesystem="${actualDeviceToFormat}"
                if ! Dev__wipeDisk "${actualDeviceToFormat}" ; then
                        _exit -79 "Failed to reset content of device ${actualDeviceToFormat}."
                fi
        else
                if Dev__wipeDisk "${actualDeviceToFormat}" ; then
                        if Dev__createSinglePartition "${actualDeviceToFormat}" "${__fstype}"  0 ; then
                                local allDevices
                                if Dev__getPartitionDevices "${actualDeviceToFormat}" allDevices ; then 
                                        _log "Partition(s): '${allDevices}'"
                                        # File system must be created on the device mapping the new partition
                                        actualDeviceForHostingFilesystem="${allDevices}"
                                else
                                        _exit -77 "Failed to retrieve created partition reference on ${actualDeviceToFormat}."
                                fi
                        else
                                _exit -78 "Failed to create a single partition on ${actualDeviceToFormat}."
                        fi
                else
                        _exit -79 "Failed to reset content of device ${actualDeviceToFormat}."
                fi
        fi

        local mkcmd
        local luksLabel

        if [ "${__fstype}" = "vera" ] ; then
                _loadDep vera                           # veracrypt
                if [ ! -v SHELL_API_DEP_LOADED["vera"] ] ; then
                        _exit -1 "Sorry, the package(s) to support VERA are not available or could not be installed. VERA volumes are not supported."
                fi
                #SUMO__VARS["PASSPHRASE"]="??"

                Term__clear
                Sumo__enterFilesystemType "Enter the type of file system to be encrypted with VERA:" __fstype
                if [ ! -z "${__fstype}" ] ; then
                        _log ""
                        Sumo__vera_createDiskFile "${actualDeviceForHostingFilesystem}" "${__fstype}"
                        return $?
                else
                        _log_err "Aborted."
                        return 1
                fi
        fi

        if [ "${__fstype}" = "luks" ] ; then
                _loadDep luks                           # cryptsetup
                if [ ! -v SHELL_API_DEP_LOADED["luks"] ] ; then
                        _log_err "Sorry, the package(s) to support LUKS are not available or could not be installed. LUKS volumes are not supported."
                        return 1
                fi                

                Term__clear

                Term__restoreCursor

                File__basename "$actualDeviceForHostingFilesystem" luksLabel
                # For luks format first the partition
                local deviceMapper
                if Sumo__luks_format "${actualDeviceForHostingFilesystem}" ; then
                        if Sumo__luks_open "$actualDeviceForHostingFilesystem" "$luksLabel" deviceMapper "${passphrase}" ; then
                                actualDeviceForHostingFilesystem="$deviceMapper"
                                # Use ext3 as luks encrypted file system
                                #__fstype="ext3"
                                Term__clear
                                Sumo__enterFilesystemType "Enter the type of file system to be encrypted with LUKS:" __fstype
                                if [ -z "${__fstype}" ] ; then
                                        _log_err "Aborted."
                                        return 1
                                fi
                        else
                                _log_err "Failed to carry out LUKS open. Please check the log file. Aborted"
                                return 1
                        fi
                else
                        _log_err "Failed to carry out LUKS formattings. Please check the log file. Aborted"
                        return 1
                fi
        fi

        mkcmd="${__SUDO__}mkfs.${__fstype} \"${actualDeviceForHostingFilesystem}\""
        _logf "COMMAND: $mkcmd" 
        eval "$mkcmd" 2>&1 #| tee -a "${__LOG_FILE__}"

        if [ "${__original_fstype}" = "luks" ] ; then
                Sumo__luks_close "$luksLabel"
        fi
        #${__SUDO__}mkfs.${__fstype} -L "${SUMO__VARS["FS_LABEL"]}" "${deviceToMount}"
}

:<<'EOF'

MAIN function

EOF

:<<'EOF'
@param[1] out filesystem selected or empty string when aborted
EOF
Sumo__enterFilesystemType()
{
        local message="$1"
        local -n __out_entered_filesystem=$2
        
        local availFstypes=(${Dev__fstypes})
        Input__cursorSelect "${Dev__fstypes}" "${_pal['bg_blue']}${message}${Term__reset_color}" 1
        local key=$?
        Term__restoreCursor
        if [ $key -ne 0 ] ; then
                __out_entered_filesystem="${availFstypes[$(($key-1))]}" 
        else
                __out_entered_filesystem=""
        fi
}

Sumo__main() {
:<<'EOF' 
echo "__SHELL_API_SYS__: ${__SHELL_API_SYS__}"
echo "__SHELL_API_NET__ :${__SHELL_API_NET__}"
echo "Dev__fstype2PartUUID :${Dev__fstype2PartUUID[@]}"
# for test
Sumo__im_resetBottomArea
local availFstypes=(${Dev__fstypes})
Input__cursorSelect "${Dev__fstypes}" "${_pal['bg_blue']}Select file system type:${Term__reset_color}" 1
local key=$?
echo $key
read tata
echo $tata
exit 0
EOF

        # PERF TEST BEGIN
        # Use this to assess performance of loaded dependency check. Uncomment linked line below too.
        # --> Normal usage: 1s, but generally closer to 2s
        #Date__startTimer SUMO__loadDepTimer

        _loadDep "lsb-release"
        _loadDep "gawk@gawk"                    # awk
        _loadDep "parted@parted"                # parted
        _loadDep "gdisk@gdisk"                  # gdisk
        _loadDep "fdisk"                        # for sfdisk
        _loadDep "udev"                         # udevadm
        _loadDep "lsblk@util-linux"             # blkid, lsblk, dmesg, findmnt, mkfs
        _loadDep "xterm@xterm"                  # resize command
        _loadDep "ip@iproute2"
        _loadDep "host@bind9-host"
        _loadDep "nslookup@bind9-dnsutils"
        _loadDep "wget"                         # For installing eg vera package over the net
        _loadDep "inotifywait@inotify-tools"    # inotifywait is required
        _loadDep "modprobe@kmod"                # Mandatory for 'modprobe'

        # PERF TEST END
        # Use this to assess performance of loaded dependency check. Uncomment linked line above too.
        #Date__elapsedSecondsTimer $SUMO__loadDepTimer secs show

#exit 0
        local allargs=("$@")

        export LC_ALL=C.UTF-8
        export LANG=EN.US.UTF-8
        
        _log_dbg "${allargs[@]}"
        if ! _parseArgs "${allargs[@]}" ; then
                _exit -1 "Failed to parse arguments"
        fi

        if [ ! -z "${SUMO__VARS["HISTORY_NAME"]}" ] ; then
                local wasInteractive="${SUMO__VARS["INTERACTIVE"]}"
                SUMO__VARS["INTERACTIVE"]="" # deactivate interactive mode for correct exit

                local recentFilename=""
                __getRecentListFilePath recentFilename
                local recentFilenameDirPath=""
                File__dirname "$recentFilename" recentFilenameDirPath

                # Handle special value to only list histories
                echo
                echo "History list:"
                echo
                ls -1 "${recentFilenameDirPath}"|awk -F'.' '{ if (($NF!="yml") && ($NF!="old")) printf(" %s\n", $NF)}'
                echo
                if [ "${SUMO__VARS["HISTORY_NAME"]}" = "@@@" ] ; then
                        _quit ""
                fi

                local recentFilenameNew=""
                local recentFilenameOld=""
                local recentFilenameBasename=""
                local recentFilenameNewBasename=""
                local recentFilenameOldBasename=""

                local newHistName
                local oldHistName
                #Term__countdown "Restoring in " 10 " calling $0 ${allargs[@]}" 

                Str__split "${SUMO__VARS["HISTORY_NAME"]}" newHistName ":" oldHistName 1
                recentFilenameNew="${recentFilename}.${newHistName}" ; 

                File__basename "$recentFilename" recentFilenameBasename
                File__basename "$recentFilenameNew" recentFilenameNewBasename

                # Check if requested history exists, and exit immediately on error
                if [ ! -f "${recentFilenameNew}" ] ; then
                        _log_err "History of name '$newHistName' does not exist"
                        _log_err "File not found: ${recentFilenameNew}"
                        # Above default listing replacing this
                        #_log "The following histories are available:"
                        #ls -1 "${recentFilenameDirPath}"|awk -F'.' '{ if ($NF!="yml") print $NF}'
                        _exit -170 "Aborted."
                        # Below code works but there might be problems if the list is at the bottom of terminal
                        # also, what happens if the list is too long?
:<<'EOF'
                        _log "You can now choose among the following files or (q)uit to abort:"
                        local histList="$(ls -1 "${recentFilenameDirPath}"|awk -F'.' '{ if ($NF!="yml") print $NF}')"
                        Input__cursorSelect "${histList}" "${_pal['bg_blue']}Choose among the following or (q)uit to abort:${Term__reset_color}" 1
                        local key=$?
                        if [ $key -eq 0 ] ; then
                                _exit -170 "Aborted."
                        fi
                        #Term__eraseLines $(echo "$histList"|wc -l) false

                        recentFilenameNew="${recentFilename}.$(echo "${histList}"| head -n $key | tail -n1 )" # This enables to manage value containing spaces
                        File__basename "$recentFilenameNew" recentFilenameNewBasename
EOF
                fi
                # Determine file were to save the previous history
                if [ -z "$oldHistName" ] ; then 
                        oldHistName="old"
                elif [ "$oldHistName" = "yml" ] ; then
                        _exit -150 "You cannot use 'yml' as an history name."
                elif [ "$oldHistName" = "old" ] ; then
                        _exit -150 "You cannot use 'old' as an history name."
                fi
                recentFilenameOld="${recentFilename}.${oldHistName}" ; 

                local oldRecentState="[ '${oldHistName}' is OVERWRITTEN ]"
                File__basename "$recentFilenameOld" recentFilenameOldBasename
                if [ ! -f "$recentFilenameOld" ] ; then
                        if ! Input__confirm "'$recentFilenameOld' does not exist yet. Create or abort?" ; then
                                _exit -170 "Aborted."
                        fi
                        oldRecentState="[ '${oldHistName}' is CREATED ]"
                fi


                # Rebuild args
                local newArgs=()
                local oldArg=""
                local nbArgs=${#allargs[@]}
                local argCnt=0
                while [ $argCnt -lt $nbArgs ] ; do
                        oldArg="${allargs[$argCnt]}"
                        if [ "$oldArg" = "-H" ] ; then
                                # Value comes next skip it as well
                                argCnt=$(($argCnt + 1))
                        elif [ "$oldArg" = "--history" ] ; then
                                # option and value are attached just ignore arg
                                :
                        else
                                newArgs+=("$oldArg")
                        fi
                        argCnt=$(($argCnt + 1))
                done

                _log "In folder ${recentFilenameDirPath}":
                _log_high "${oldRecentState} : going to move ${recentFilenameBasename} to ${recentFilenameOldBasename}"
                _log_high "[ ${newHistName} is RESTORED ] : going to restore ${recentFilenameBasename} from ${recentFilenameNewBasename}"

                Input__getForcedInput forcedInput
                if [ "$forcedInput" == "y" ] ; then
                        _log "Restarting with $(basename $0) ${newArgs[*]}"
                else
                        read -n 1 -p "Press a key to apply and restart with $(basename $0) ${newArgs[*]}"
                fi
                echo
                cp "${recentFilenameOld}" "${recentFilenameOld}.old" &>/dev/null # Create a backup of overwritten history. It may not exist when creating a new one
                cp "${recentFilename}" "${recentFilenameOld}"
                cp "${recentFilenameNew}" "${recentFilename}"

                if [ ! -z "${wasInteractive}" ]  ; then
                        exec $0 ${newArgs[@]}
                fi
                #Term__countdown "Restoring in " 2 " calling $(basename $0) ${allargs[*]}" 

                _quit ""
        fi

        #_loadDep "bind9-dnsutils"               # nslookup
        # sshfs and smb deps are loaded on demand

        if [ ${SUMO__VARS["RUN_TESTS"]} -eq 0 ]; then
                if [ -z "${SUMO__VARS["TEST_NAME"]}" ]; then
                        _testAll
                elif [ "${SUMO__VARS["TEST_NAME"]}" == "@sumotestdoc" ]; then
                        __SHELL_TEST_GEN_EXAMPLES__=0
                        _testAll
                else
                        _testCase "${SUMO__VARS["TEST_NAME"]}"
                fi
                return 0
        fi

        # Mark all known items as not-mounted
        Sumo__resetNotMountStatus

        if Sumo__overlay ; then
                _quit ""
        fi

        if Sumo__network ; then
                _quit ""       
        fi

        if Sumo__cloud ; then
                _quit ""       
        fi

        if Sumo__usb ; then
                _quit ""       
        fi

        if Sumo__isLuks  ; then
                _loadDep luks                           # cryptsetup
                if [ ! -v SHELL_API_DEP_LOADED["luks"] ] ; then
                        _exit -1 "Sorry, the package(s) to support LUKS are not available or could not be installed. LUKS volumes are not supported."
                fi                
        fi

        if Sumo__isVera  ; then
                _loadDep vera                           # veracrypt
                if [ ! -v SHELL_API_DEP_LOADED["vera"] ] ; then
                        _exit -1 "Sorry, the package(s) to support VERA are not available or could not be installed. VERA volumes are not supported."
                fi                
        fi

        if Sumo__isVirt ; then
                _loadDep virt
                if [ ! -v SHELL_API_DEP_LOADED["virt"] ] ; then
                        _exit -1 "Sorry, the package(s) to support QEMU and VM disk files are not available or could not be installed. VM disk files are not supported."
                fi     
        fi 

        Sumo__resolveBlockDeviceInfos
        #_log "'${SUMO__VARS["NET_PROTO"]}' '${SUMO__VARS["DEVPART"]}' '${SUMO__VARS["DEVMAPPER"]}'"
        #exit 0

        if [ ${SUMO__VARS["DO_UNMOUNT"]} -eq 0 ]; then
                Sumo__unmount  # This should be the last step
                _exit -1 "Internal error - Script did not exit after unmount."
                # Otherwise, let unmount as programmed below for devices
        fi
        SUMO__CURRENT_OPERATION="mount"

        if ${SUMO__VARS["FORMAT_DISK"]} ; then
                Sumo__formatDisk "${SUMO__VARS["FS_TYPE"]}" "${SUMO__VARS["PASSPHRASE"]}"
                if [ $? -eq 0 ] ; then
                        _quit "Success"
                else
                        _exit -80 "Failed to create file system (file/dev:'${SUMO__VARS["IMG_FILE"]}${SUMO__VARS["DEV"]}')."
                fi
        fi

        if [ ! -z "${SUMO__VARS["FLASH_DISK"]}" ] ; then
                Sumo__flashDisk "${SUMO__VARS["FLASH_DISK"]}" "${SUMO__VARS["IMG_FILE"]}"
                if [ $? -eq 0 ] ; then
                        _quit "Success"
                else
                        _exit -81 "Failed to flash disk '${SUMO__VARS["FLASH_DISK"]}' on '${SUMO__VARS["IMG_FILE"]}')."
                fi
        fi

        if [ ! -z "${SUMO__VARS["PART_DISK"]}" ] ; then
                Sumo__partDisk "${SUMO__VARS["PART_DISK"]}" "${SUMO__VARS["IMG_FILE"]}"
                if [ $? -eq 0 ] ; then
                        _quit "Success"
                else
                        _exit -81 "Failed to partition disk '${SUMO__VARS["PART_DISK"]}' on '${SUMO__VARS["IMG_FILE"]}')."
                fi
        fi

        if [ ${SUMO__VARS["CREATE_FILE"]} -eq 0 ] ; then
                _log ""
                Input__confirm "Disk file '${SUMO__VARS["IMG_FILE"]}' does not exist. Do you want to create it?"                                
                if [ $? -ne 0 ] ; then
                        _log ""
                        _quit "Aborted."
                fi
                _log ""

                if Sumo__isVera ; then
                        Sumo__vera_createDiskFile "${SUMO__VARS["IMG_FILE"]}" "${SUMO__VARS["FS_TYPE"]}" "${SUMO__VARS["PASSPHRASE"]}"
                elif Sumo__isVirt ; then
                        Sumo__virt_createDiskFile
                else
                        Sumo_createDiskFile # This handles LUKS as well
                fi                        
                if [ $? -eq 0 ] ; then
                        SUMO__VARS["IMG_DISK_FILE_PATH"]="${SUMO__VARS["IMG_FILE"]}"
                else
                        _exit -1 "Failed to create disk. If necessary, cleanup file '${SUMO__VARS["IMG_FILE"]}'"
                fi
        fi

        # The check here below are done for the cases of a mounting or a creation (not unmounting)
        if [ ! -z "${SUMO__VARS["MOUNT_POINT"]}" ] ; then
                Sumo__manageValidMountpointSetting Sumo__getMountpoint "${SUMO__VARS["MOUNT_POINT"]}"                        
        elif [ "${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]}" -eq 0 ] ; then
                Sumo__manageValidMountpointSetting Sumo__getMountpoint 
        elif [ -z "${SUMO__VARS["IMG_FILE"]}" ] ; then
                if [ ! -z "${SUMO__VARS["FS_LABEL"]}" ] ; then
                        Sumo__manageValidMountpointSetting Sumo__getMountpoint 
                else
                        _susage "Please specify at least a disk image file."
                fi
        else
                if ! Sumo__isVera && [ ${SUMO__VARS["CREATE_FILE"]} -ne 0 ] && [ ! -z "${SUMO__VARS["FS_LABEL"]}" ] ; then
                        # For VERA label are not definitive, a new label can be specified at mounting
                        _susage "Invalid arguments: label is not relevant for mounting disk file ${SUMO__VARS["IMG_FILE"]}."
                fi

                Sumo__manageValidMountpointSetting Sumo__getMountpoint 
        fi

        #Sumo__toYAML # debug
        
        # Handle specific mounting processes
        if Array__contains_by_string "${SUMO__VARS["SUMO__VERA_EXTENSIONS"]}" "${SUMO__VARS["IMG_TYPE"]}"; then
                local labelMount
                if [ -z "${SUMO__VARS["FS_LABEL"]}" ] ; then labelMount="-" ; fi
                Sumo__vera_mount "${SUMO__VARS["IMG_FILE"]}" "${SUMO__VARS["MOUNT_POINT"]}" "${labelMount}" "${SUMO__VARS["PASSPHRASE"]}"
                return $?
        fi

        _log_dbg "SUMO__VARS["DEV"]: '${SUMO__VARS["DEV"]}'"
        #exit 0
        # Lets continue for other images
        # Manage allocation of the necessary block device for disk files
        if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] && [ "${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]}" -ne 0 ]  ; then
                local allDevices
                local diskBlockDev
                if Array__contains_by_string "${SUMO__VARS["VIRTDISK_EXTENSIONS"]}" "${SUMO__VARS["IMG_TYPE"]}"; then
                        SUMO__VARS["BLK_TYPE"]="nbd"
                        BLKTYPE="nbd"
                        if [ -z "${SUMO__VARS["DEV"]}" ] ; then
                                if ! Sumo__virt_nbd_open "${SUMO__VARS["IMG_FILE"]}" "${SUMO__VARS["IMG_TYPE"]}" diskBlockDev ; then
                                        _exit -127 "failed to setup NBD device"
                                else
                                        SUMO__VARS["DEV"]="$diskBlockDev"
                                fi
                        fi

                        Dev__getPartitionDevices "${SUMO__VARS["DEV"]}" allDevices
                        SUMO__VARS["DEVPART"]="$allDevices"
                else
                        SUMO__VARS["BLK_TYPE"]="loop"
                        BLKTYPE="loop"
                        _log_dbg "Trying to allocate loop for ${SUMO__VARS["IMG_FILE"]}, DEV='${SUMO__VARS["DEV"]}' DEVPART='${SUMO__VARS["DEVPART"]}'"
                        if [ -z "${SUMO__VARS["DEV"]}" ] ; then
                                _log_dbg "Allocating loop for ${SUMO__VARS["IMG_FILE"]}"

                                if ! Dev__loop_open "${SUMO__VARS["IMG_FILE"]}" "${SUMO__VARS["IMG_TYPE"]}" diskBlockDev ; then
                                        _exit -127 "Failed to setup loop device. Please check log."
                                else
                                        SUMO__VARS["DEV"]="$diskBlockDev"
                                        _log_dbg "Created loop device '${SUMO__VARS["DEV"]}'"
                                fi
                        fi

                        # This enables to create the block device for the new partition below /dev/. E.g. /dev/loop0p1
                        Dev__getPartitionDevices "${SUMO__VARS["DEV"]}" allDevices
                        SUMO__VARS["DEVPART"]="$allDevices"
                fi

                if [ -z "${SUMO__VARS["DEVPART"]}" ] ; then
                        _log_warn "No partition could be identified from '${SUMO__VARS["IMG_FILE"]}'". 
                        Input__confirm "Do you want to install a new file system (ANY DATA WILL BE LOST)?"                        
                        if [ $? -eq 0 ] ; then
                                _log ""
                                local selectedFS=""
                                Sumo__enterFilesystemType "Select file system type:" selectedFS
                                if [ ! -z "${selectedFS}" ] ; then
                                        Sumo__formatDisk "${availFstypes[$(($key-1))]}"
                                        if [ $? -ne 0 ] ; then
                                                _exit -80 "Failed to create file system on '${actualDeviceForHostingFilesystem}'."
                                        fi
                                else
                                        _exit -62 "Unable to continue. Aborted."
                                fi

:<<'EOF'                                
                                if Dev__createSinglePartition "${SUMO__VARS["DEV"]}" 0 ; then
                                        Dev__getPartitionDevices "${SUMO__VARS["DEV"]}" allDevices
                                        SUMO__VARS["DEVPART"]="$allDevices"
                                else
                                        _exit -62 "Unable to continue. Aborted."
                                fi
EOF
                        else
                                _exit -62 "Failed to identify partitions from '${SUMO__VARS["IMG_FILE"]}'. Is the device content valid?"
                        fi
                fi
        fi

        _log_dbg "SUMO__VARS["DEVPART"]: '${SUMO__VARS["DEVPART"]}' mounted flag: '${SUMO__VARS["MOUNTED"]}' mountpoint: '${SUMO__VARS["MOUNT_POINT"]}'"

        local allDeviceList=(${SUMO__VARS["DEVPART"]})
        local deviceCnt=0
        _log_dbg "All devices: ${allDeviceList[@]}"
        #exit 0
        local mountFinalRes=0
        local nbMountFail=0
        while [ $deviceCnt -lt ${#allDeviceList[@]} ]
        do
                local currentDevice="${allDeviceList[$deviceCnt]}"
                local currentMountpoint
                deviceCnt=$(($deviceCnt+1))

                if Str__startsWith "$currentDevice" "VG:" ; then
                        Str__toTail currentDevice "VG:" last
                        if ! ${__SUDO__}vgchange -a y "$currentDevice" ; then
                                _exit -67 "Failed to activate LVM Volume Group '$currentDevice'"
                        fi
                        continue # The next are the activated volumes inside the VG
                fi

                if [ ${#allDeviceList[@]} -eq 1 ] ; then
                        currentMountpoint="${SUMO__VARS["MOUNT_POINT"]}"
                else
                        local devBasename
                        File__basename "${currentDevice}" devBasename
                        currentMountpoint="${SUMO__VARS["MOUNT_POINT"]}/${devBasename}"
                        mkdir -p "${currentMountpoint}" 2>/dev/null
                fi

                if [ ! -e "$currentDevice" ] ; then
                        # Wait max 4s till item to appear
                        local timestamp=$(date +%s)
                        local timestampEnd=$(($timestamp + 5))
                        local devbasename=$(basename "$currentDevice")
                        while [ $timestamp -lt $timestampEnd ] ; do
                                printf "\rWaiting for $currentDevice to be available $(($timestampEnd - $timestamp))"
                                local waitForDevice=$(inotifywait -q -e close_write -t 1  "/dev"|grep -E "$devbasename"$)
                                if [ ! -z "$waitForDevice" ] || [ -e "$currentDevice" ] ; then
                                        break
                                fi
                                timestamp=$(date +%s)
                        done

                        if [ ! -e "$currentDevice" ] ; then
                                _exit -125 "Partition block device '$currentDevice' is not present as expected."
                        fi
                fi
:<<'EOF'
        # The reason for the tail and head command:
        > lsblk -o FSTYPE,TYPE /dev/loop28
        FSTYPE TYPE
        loop
        ext4   part
EOF

                if [ ${SUMO__VARS["CREATE_FILE"]} -ne 0 ] ; then        
                        FSTYPE="$(lsblk -n -o FSTYPE "$currentDevice"|tail -n1)"
                        # BLKTYPE="$(lsblk -n -o TYPE "$currentDevice"|head -n1)"  # Not useful at the moment. At least set above when using loop.
                        if [ ! -z "$FSTYPE" ] ; then
                                SUMO__VARS["FS_TYPE"]="$FSTYPE"
                        else
                                local PARTTYPE="$(lsblk -n -o PARTTYPE "$currentDevice"|tail -n1)"
                                Str__toUpper PARTTYPE
                                #local allPartTypeUUID="${Dev__fstype2PartUUID[@]}"
                                #_log_vars PARTTYPE allPartTypeUUID
                                local parttypename=""
                                for parttypename in "${!Dev__fstype2PartUUID[@]}" ; do
                                        if [ "${Dev__fstype2PartUUID["$parttypename"]}" = "${PARTTYPE}" ] ; then break; fi
                                done
                                if [ ! -z "${parttypename}" ]; then
                                        if [ "$parttypename" = "vera" ]  ; then
                                                _log_dbg "FSTYPE deduced from PARTTYPE: '${parttypename}'"
                                                SUMO__VARS["IMG_FILE_IS_BLK_DEV"]=0
                                                _loadDep vera                           # veracrypt
                                                local labelMount
                                                if [ -z "${SUMO__VARS["FS_LABEL"]}" ] ; then labelMount="-" ; fi
                                                Sumo__vera_mount "${SUMO__VARS["IMG_FILE"]}" "${SUMO__VARS["MOUNT_POINT"]}" "${labelMount}" "${SUMO__VARS["PASSPHRASE"]}"
                                                return $?
                                        else
                                                # Lets try this way, but not 100%sure
                                                _log_dbg "FSTYPE not set, but set to PARTTYPE: '${parttypename}'"
                                                FSTYPE="$parttypename"
                                        fi
                                fi
                        fi
                fi
                _log_dbg "FSTYPE=$FSTYPE BLKTYPE=$BLKTYPE"

                #EXPECTED_BLKTYPE=$(Sumo__findBlkTypeFromImageType "${SUMO__VARS["IMG_TYPE"]}") # CURRENTLY NOT USED

                # If no volume label was specified, try to resolve it :
                # 1. check if such label exists using lsblk
                # 2. when not, take the corename of the image file. For luks, this will be used
                # as the LUKS volume name
                if [ -z "${SUMO__VARS["FS_LABEL"]}" ] ; then
                        # If the device has no label, take the file core name                
                        #SUMO__VARS["FS_LABEL"]="$(Str__trim "$(lsblk -n -o LABEL "$currentDevice"|head -n1)" ' ' recurse)"
                        local label
                        Dev__getBlockDeviceLabel "$currentDevice" label
                        SUMO__VARS["FS_LABEL"]="$label"
                        _log_dbg "found volume label: '${SUMO__VARS["FS_LABEL"]}' for DEVPART=$currentDevice"
                        if [ -z "${SUMO__VARS["FS_LABEL"]}" ] ; then
                                if [ ! -z "${SUMO__VARS["IMG_FILE"]}" ] ; then
                                        local corename
                                        File__corename "${SUMO__VARS["IMG_FILE"]}" corename
                                        SUMO__VARS["FS_LABEL"]="$corename"
                                else
                                        _susage "unable to determine volume label for further operation. Please specify a volume label with -L or a disk file with -f."
                                fi
                        fi
                fi

                _log_dbg "FSTYPE='$FSTYPE' BLKTYPE='$BLKTYPE'"
                if Sumo__isLuks || [ "$FSTYPE" == "crypto_LUKS" ] ; then
                        Sumo__initDataLUKS        
                fi


# Actually this test does not work. If Luks is not yet open, the block type will be 'part'. It is 'part' + 'crypt' only once open
#_log "BLK TYPE = '$BLKTYPE' expected='${EXPECTED_BLKTYPE}'"
# if [ ${SUMO__VARS["CREATE_FILE"]} -ne 0 ] ; then
#         if [ "${BLKTYPE}" != "${EXPECTED_BLKTYPE}"  ] ; then
#                _log "The block device is of type '${BLKTYPE}', whereas '${EXPECTED_BLKTYPE}' was expected. Total size available: $(Dev__blockDeviceSize "${SUMO__VARS["DEVPART"]}")".
#                if Sumo__isLuks ; then
#                        Input__confirm "Do you want to format/reformat the disk as a luks?"                                
#                        SUMO__VARS["CREATE_FILE"]=$?
                        #else, the opening of luks will fail
#                fi
#        else
#                _log "Detected ${FSTYPE} file system. Total size: $(Dev__blockDeviceSize "${SUMO__VARS["DEVPART"]}")"
#        fi
#fi
#                _log "The block device is disk does not contain any known file system. Total size available: $(Dev__blockDeviceSize "${SUMO__VARS["DEVPART"]}")".

                if [ -z "${FSTYPE}" ] ; then
                        if [ ${SUMO__VARS["CREATE_FILE"]} -ne 0 ] ; then
                                _log "The block device of size $(Dev__blockDeviceSize "$currentDevice") does not contain any known file system.".
                                if Sumo__isLuks ; then
                                        Input__confirm "Do you want to format/reformat the disk as a luks?"  
                                        SUMO__VARS["CREATE_FILE"]=$?
                                        _log ""
                                        #else, the opening of luks will fail
                                fi
                        fi
                fi

                # Handle the luks stuff
                # NOTE this part is only valid for disk files!
                local cryptopen_res=0
                if Sumo__isLuks ; then
                        _log_dbg "Current device luks $currentDevice"
                        if [ ${SUMO__VARS["CREATE_FILE"]} -eq 0 ] ; then
                                _log "Formatting partition as a LUKS disk"
                                Sumo__luks_format "$currentDevice" "${SUMO__VARS["PASSPHRASE"]}" 
                                cryptopen_res=$?
                                FSTYPE="crypto_luks" # Need by sumo__mount
                        fi
                        SUMO__VARS["DEVMAPPER"]="$currentDevice"                        
:<<'EOF'
                        if [ ${cryptopen_res} -eq 0 ] ; then
                                local deviceMapper

                                Sumo__luks_open "$currentDevice" "${SUMO__VARS["FS_LABEL"]}" deviceMapper "${SUMO__VARS["PASSPHRASE"]}"
                                cryptopen_res=$?

                                # For LUKS, the actual label is known only after opening the Luks device with cryptsetup. 
                                if [ ${SUMO__VARS["CREATE_FILE"]} -ne 0 ] ; then
                                        local label
                                        Dev__getBlockDeviceLabel "$currentDevice" label
                                        SUMO__VARS["FS_LABEL"]="$label"
                                fi
                        fi
EOF
                else
                        SUMO__VARS["DEVMAPPER"]="$currentDevice"
                fi

                if [ ${cryptopen_res} -eq 0 ] ; then
                        # At the moment, the mount options are applied globally for all contained FS.
                        Sumo__mount "${SUMO__VARS["DEVMAPPER"]}" "$currentMountpoint" "${SUMO__VARS["MOUNT_OPTIONS"]}"
                        local mountRes=$?
                        if [ $mountRes -ne 0 ] ; then 
                                mountFinalRes=$mountRes
                                nbMountFail=$(($nbMountFail + 1))
                        fi
                else
                        _log_err "failed to open device."
                        if [ ${SUMO__VARS["CREATE_FILE"]} -eq 0 ] ; then
                                Input__confirm "Do you want to remove the disk file ${SUMO__VARS["IMG_FILE"]}?"  
                                if [ $? -eq 0 ] ; then
                                        _log_err "removing created file ${SUMO__VARS["IMG_FILE"]}"
                                        rm -f "${SUMO__VARS["IMG_FILE"]}"
                                        _exit -63 "Aborted."
                                fi
                        else
                                _exit -63 "Unable to continue. Aborted."
                        fi
                        mountFinalRes=1
                fi
        done

        # List
        if [ $nbMountFail -lt ${#allDeviceList[@]} ] ; then
                Sumo__listCurrentDevice
                # Update recent for disk file itself
                if Sumo__isDiskFile ; then
                        Sumo__updateSavedRecentList "${SUMO__VARS["IMG_DISK_FILE_PATH"]}"  "${SUMO__VARS["MOUNT_POINT"]}" "${SUMO__VARS["IMG_DISK_FILE_PATH"]}" "mount"
                fi

        fi

        if [ $nbMountFail -gt 0 ] && [ $nbMountFail -ne ${#allDeviceList[@]} ]; then
                _log_warn "Mounting was only partially successful. Please check overall mount status with command '$0 [-i]' if necessary."
        fi

        return $mountFinalRes
}


:<<'EOF'
Generic low-level mount wrapper function. 
If FS is not ext*, it will be attempted to use the mount options uid and gid. 
Otherwise, ownership and access rights of the mount point are set according to current user and mask.

@param [1] Device to mount is expected 
@param [2] Mountpoint
@param [3] Mount options

Used global vars:
SUMO__VARS["CREATE_FILE"]: disk file that was originally created and containing the FS to mount
SUMO__VARS["IMG_DISK_FILE_PATH"]: path to the disk file is root device is a disk file
SUMO__VARS["MOUNT_POINT_CREATED"]: tells whether top root mount point was created
SUMO__VARS["FSTYPE"] and FSTYPE: type of file system to mount (it is set in the loop of mount at each iteration)
SUMO__VARS["FS_LABEL"]: label of file system to mount (it is set in the loop of mount at each iteration)
SUMO__VARS["SECURITY_MASK"]: file mask for the mountpoint
EOF

Sumo__mount()
{
        _log_dbg "Sumo__mount '$1', '$2 , $3"
        local deviceToMount="$1"
        local mountPoint="$2"
        local mountOptions="$3"

        local lowerFsype="$FSTYPE"
        Str__toLower lowerFsype
        _log_dbg "fstype:'$lowerFsype' LABEL: '${SUMO__VARS["FS_LABEL"]}', VOLUME NAME: '${SUMO__VARS["VOLUME_NAME"]}'"
        if [ "$lowerFsype" = "crypto_luks" ] ; then
                local label="${SUMO__VARS["FS_LABEL"]}"
                if [ ! -z "${SUMO__VARS["VOLUME_NAME"]}" ] ; then
                        label="${SUMO__VARS["VOLUME_NAME"]}"
                        SUMO__VARS["FS_LABEL"]="$label"
                elif [ -z "${label}" ] ; then
                        File__basename "$1" label
                        SUMO__VARS["FS_LABEL"]="$label"
                fi
                _log_dbg "fstype:'$lowerFsype' LABEL: '${label}'"
                local deviceMapper
                # Open luks. This updates the actual device path with the mapper device created after opening
                if ! Sumo__luks_open "$1" "$label" deviceToMount "${SUMO__VARS["PASSPHRASE"]}" ; then
                        return 1
                fi
                # Update the fstype with the one of the device mapper
                Dev__getDeviceFSType "$deviceToMount" FSTYPE

                # For LUKS, the actual label is known only after opening the Luks device with cryptsetup. 
                if [ ${SUMO__VARS["CREATE_FILE"]} -ne 0 ] ; then
                        local label
                        Dev__getBlockDeviceLabel "$currentDevice" label
                        SUMO__VARS["FS_LABEL"]="$label"
                fi
        fi

        # For LUKS, the actual label is only known after opening the Luks device with cryptsetup. 
        # Therefore, this informational display is done at this place.
        if [ -z "${SUMO__VARS["SILENT"]}" ] ; then 
                _log_dbg "System label: ${SUMO__VARS["FS_LABEL"]}"
        fi

        if [ ${SUMO__VARS["CREATE_FILE"]} -eq 0 ] ; then
                _log "Formatting disk image with file system type ${SUMO__VARS["FS_TYPE"]} and label '${SUMO__VARS["FS_LABEL"]}'"
                local _labelOptMkfs=""
                if [ ! -z "${SUMO__VARS["FS_LABEL"]}" ] ; then 
                        case "${SUMO__VARS["FS_TYPE"]}" in 
                                exfat|vfat|fat) 
                                        _labelOptMkfs="-n \"${SUMO__VARS["FS_LABEL"]}\""; 
                                ;;
                                ext2|ext3|ext4|ntfs) 
                                        _labelOptMkfs="-L \"${SUMO__VARS["FS_LABEL"]}\""; 
                                ;;
                                *) 
                                        _log_warn "Assigning a label (here '${SUMO__VARS["FS_LABEL"]}') is not supported for file system of type '${SUMO__VARS["FS_TYPE"]}'."                                        
                                ;;
                        esac                
                fi
                local _fmtcmd="${__SUDO__}mkfs.${SUMO__VARS["FS_TYPE"]} ${_labelOptMkfs} \"${deviceToMount}\""
                _logf "MKFS COMMAND: ${_fmtcmd}"
                eval "${_fmtcmd}" 2>&1 #| tee -a "${__LOG_FILE__}"
                #${__SUDO__}mkfs.${SUMO__VARS["FS_TYPE"]} -L "${SUMO__VARS["FS_LABEL"]}" "${deviceToMount}"
        elif  [ -z "$FSTYPE" ]; then
                _log_warn "No file system was detected for device '$deviceToMount'. Ignored, no mount done on '$mountPoint'"
                return 1
:<<'EOF'
                Input__confirm "No file system was detected. Do you want to format disk as ${SUMO__VARS["FS_TYPE"]} ?"
                if [ $? -ne 0 ] ; then
                        _exit -60 "Aborted."
                fi
EOF
        elif [ "$FSTYPE" == "swap" ]; then
                _log_warn "Swap partition detected on '$deviceToMount'. Ignored, no mount done on '$mountPoint'"
                return 1
        fi

        local mntcmd="${__SUDO__}mount"                
        local optSep=""
        local option=""
        if [ ! -z "${mountOptions}" ] ; then
                optSep=","
                option="-o " # put the space here
        fi

        local uidOptionsAccepted=1
        if [ ${SUMO__VARS["IMG_FILE_IS_BLK_DEV"]} -eq 0 ] && [[ ! "$FSTYPE" =~ ^ext ]] ; then 
                uidOptionsAccepted=0
        fi

        if [ $uidOptionsAccepted -eq 0 ] ; then 
                option="-o "                        
                mountOptions="uid=$(id -u),gid=$(id -g)${optSep}${mountOptions}" # TODO complete the cases this actually is working and not!
        fi
        mntcmd="$mntcmd ${option}${mountOptions} \"${deviceToMount}\" \"${mountPoint}\""
        _logf "MOUNT COMMAND: $mntcmd"
        eval "$mntcmd" 2>&1 #| tee -a "${__LOG_FILE__}"
        if [ $? -eq 0 ] ; then
                _log "Successfully mounted '${mountPoint}' from '${deviceToMount}'."

                Sumo__updateSavedRecentList "${deviceToMount}" "${mountPoint} " "${SUMO__VARS["IMG_DISK_FILE_PATH"]}" "mount"

        else
                _log_err "Mount failed for ${deviceToMount}."
                return 1
        fi
        #_log "uidOptionsAccepted=$uidOptionsAccepted MOUNT_POINT_CREATED=${SUMO__VARS["MOUNT_POINT_CREATED"]}"
        if [ $uidOptionsAccepted -ne 0 ] ; then 
                if [ ${SUMO__VARS["MOUNT_POINT_CREATED"]} -eq 0 ] ; then
                        local install_cmd=""
                        local filePermMask="${SUMO__VARS["SECURITY_MASK"]}" # "$(umask)"
                        install_cmd=$(printf "${__SUDO__}install -d -o $(id -u) -g $(id -g) -m %o \"${mountPoint}\"" $((0777 & ~$filePermMask)))
                        #install_cmd="${__SUDO__}chown ${USER}:${USER} \"${mountPoint}\" && chmod $((0777 & ~ $(umask)))"                                
                        _logf "INSTALL COMMAND : ${install_cmd}"
                        eval "${install_cmd}" >/dev/null 2>&1 #| tee -a "${__LOG_FILE__}"
                fi
        fi
        
        return 0
}

:<<'EOF'
In the read recent list, replace file path with the real file path to manage paths containing symbolic link
The original path specified by user will be restored when saving the recent list
The original path will be kept in the saved recent list, but internally the AWK listing will always deal with the realpath
EOF

Sumo__readRecentListPostCallback()
{
        declare -A NEW_SUMO__RECENT
        local key
        for key in "${!SUMO__RECENT[@]}"
        do
                #_log " Sumo__readRecentListPostCallback SUMO__RECENT["$key"]'"
                local unescapedKey=${key//§/ } 
                if Str__startsWith "$unescapedKey" "/" && ! Net__isUNC "$unescapedKey"; then
                #if [ -f "$unescapedKey" ] ; then
                        local fullpath="$(realpath -m "$unescapedKey")"
                        #_log " Sumo__readRecentListPostCallback fullpath= $fullpath' unescapedKey:'$unescapedKey'"
                        #local recentKey=${fullpath// /§} # Escape spaces when used as keys to enable proper saving                        
                        if [ "$fullpath" != "$unescapedKey" ] ; then
                                local recentKey=${fullpath// /§} # Escape spaces when used as keys to enable proper saving                        
                                NEW_SUMO__RECENT["$recentKey"]="${SUMO__RECENT["$key"]}"
                                SUMO__RECENT_KEY_INDIRECTION["$recentKey"]="$key"
                                #echo "CHANGED in history:  key '$key' for key '$fullpath' = ${NEW_SUMO__RECENT["$fullpath"]}, removed recent for '$key' = ${SUMO__RECENT["$key"]}" >&2
                        fi
                fi
        done        
        for key in "${!NEW_SUMO__RECENT[@]}"
        do
                SUMO__RECENT["$key"]="${NEW_SUMO__RECENT["$key"]}"
                #echo "SUMO__RECENT["$key"] = '${SUMO__RECENT["$key"]}'" >&2
                local removedKey="${SUMO__RECENT_KEY_INDIRECTION["$key"]}"
                unset SUMO__RECENT["$removedKey"]
                #echo "unsetting for key $removedKey, now value is '${SUMO__RECENT["$removedKey"]}'" >&2
        done
        #exit 0
}

allArgs=("$@")
if _main "${allArgs[@]}" ; then
        if [ -z "${SUMO__VARS["SILENT"]}" ] ; then 
                _quit "Operation finished."
        else
                _quit ""
        fi
else
        _exit -1 "Operation ended with a failure. Please check above messages."
fi
