From 14cbb742f19b2d6a15c320444e02ef285a81a84d Mon Sep 17 00:00:00 2001
From: "Hahn Axel (hahn)" <axel.hahn@iml.unibe.ch>
Date: Thu, 27 May 2021 16:03:41 +0200
Subject: [PATCH] update backup/ restore... WIP

---
 README.md                     |  16 +++-
 plugins/transfer/_template.sh |  50 ++++++++++++
 plugins/transfer/duplicity.sh | 146 ++++++++++++++++++++++++----------
 plugins/transfer/restic.sh    |  75 +++++++++++------
 restore.sh                    | 109 ++++++++++++++-----------
 transfer.sh                   |  16 ++--
 6 files changed, 288 insertions(+), 124 deletions(-)

diff --git a/README.md b/README.md
index a792d37..702839e 100644
--- a/README.md
+++ b/README.md
@@ -16,10 +16,12 @@ We want to push data from a private network to target; a central backup server w
 
 A set of database backup scripts detects exsiting locally running database servers and puts a compressed dump file per database scheme to a local backup directory.
 
-Then a transfer script uses duplicity to encrypt and transfer local backups and other local folders to a backup target.
+Then a transfer script uses a tool to encrypt and transfer local backups and other local folders to a backup target.
 
 ## Features ##
 
+### Database dumps ###
+
 Supported Databases for backup and restore
 
 * Mysql/ Mariadb (mysql_dump)
@@ -31,7 +33,9 @@ Limited support:
 * couchdb (using a config with naming convention)
 * ldap (without restore so far)
 
-Duplicity allows
+### backup tools ###
+
+DUPLICITY
 
 * Incremental and full backups
 * encrypted backups using GPG
@@ -39,6 +43,14 @@ Duplicity allows
 * delete old backups by a given time limit
 * several backup targets (we currently use scp:// rsync:// and file://)
 
+RESTIC
+
+* creates an initial full backup - and then never again.
+* encrypts data
+* deduplicates files
+* delete backups by rules to keep a count of hourly, daily, weekly, mothly, yearly backups
+* several backup targets (we currently use sftp:// http:// and file://)
+
 ## Installation ##
 
 - Uncompress / clone the client to a local directory
diff --git a/plugins/transfer/_template.sh b/plugins/transfer/_template.sh
index d0f7e6e..4009f07 100644
--- a/plugins/transfer/_template.sh
+++ b/plugins/transfer/_template.sh
@@ -135,6 +135,56 @@
     function t_cmdShowVolumes(){
     }
 
+    # select a snapshot to restore from
+    function t_restoreSelect(){
+        local _selid=
+        echo "--- Existing snapshots:"
+        color cmd
+        t_cmdShowVolumes
+        color reset
+        showPrompt "ID of the snapshot or \"latest\" to restore from [${RESTORE_ITEM}] >"
+        read _selid
+        test -z "$_selid" && _selid=${RESTORE_ITEM}
+        RESTORE_ITEM=${_selid}
+
+        test "$RESTORE_ITEM" = "latest" && RESTORE_ITEMINFO="automatic value"
+        test "$RESTORE_ITEM" = "latest" || RESTORE_ITEMINFO=$( t_cmdShowVolumes | grep "^${RESTORE_ITEM} " | awk '{ print $2 " " $3} ' )
+
+        if [ -z "${RESTORE_ITEMINFO}" ]; then
+            color error
+            echo ERROR: A napshot ID \"${_selid}\" does not exist.
+            RESTORE_ITEM=latest
+            color reset
+        fi
+        echo using \"${RESTORE_ITEM}\"
+        echo
+    }
+
+    # set a filter to reduce count of files to restore
+    function t_restoreFilter(){
+        local _inc=
+        echo "You can enter ..."
+        echo "  - a single directory name anywhere in the folderstructure"
+        echo "  - a filename without path"
+        echo "  - a filemask"
+        showPrompt "Include >"
+        read _inc
+        RESTORE_FILTER="$( t_getParamInlude "${_inc}" )"
+        echo using parameter \"${RESTORE_FILTER}\"
+        echo
+    }
+    # show stored volumes on backup repository
+    # used in restore; directory param is checked before
+    # param  string  name of backup dir, i.e. /etc
+    function t_cmdRestore(){
+        echo ""
+    }
+
+    # Mount backup data
+    function t_restoreDoMountBackupdata(){
+
+    }
+
 # --------------------------------------------------------------------------------
 # VERIFY RETURNCODES
 # --------------------------------------------------------------------------------
diff --git a/plugins/transfer/duplicity.sh b/plugins/transfer/duplicity.sh
index 1768e47..5ad157e 100644
--- a/plugins/transfer/duplicity.sh
+++ b/plugins/transfer/duplicity.sh
@@ -10,12 +10,6 @@
 # 2021-05-19  ah    v0.0   INIT ... WIP
 # ================================================================================
 
-# --------------------------------------------------------------------------------
-# ENV VARS
-# export variables that are needed by the backup tool
-# --------------------------------------------------------------------------------
-
-export PASSPHRASE
 
 # --------------------------------------------------------------------------------
 # INIT
@@ -23,16 +17,15 @@ export PASSPHRASE
 
     # check requirements
     function t_checkRequirements(){
-        echo "DEBUG: function t_checkRequirements"
-
-        j_requireUser "root"
         j_requireBinary "duplicity"
+        j_requireUser "root"
     }
 
     # set variables
     function t_setVars(){
-        echo "DEBUG: t_setVars"
-
+        export PASSPHRASE
+        RESTORE_ITEM=$( date +%Y-%m-%d )
+        RESTORE_FILTER=
     }
 
 # --------------------------------------------------------------------------------
@@ -43,9 +36,7 @@ export PASSPHRASE
     # param  string  param1 of transfer.sh; one of full|inc|auto
     # param  string  param2 of transfer.sh; for auto: date i.e. 3M for 3 monthes
     function t_getParamDefault(){
-
         local _method=
-        local _volsize=
 
         # --- method
         test "$1" = "full" && _method="full"
@@ -59,24 +50,25 @@ export PASSPHRASE
             echo -n " --ssh-backend $sSshBackend"
         fi
 
+        # --- verbosity level to fetch changed files from log
+        echo -n " -v8"
+    }
+
+    # return a string with backup parameters that will be added to defaults
+    function t_getParamBackup(){
+
+        local _volsize=
+
+        # --- add asynchronous upload
+        echo -n " --asynchronous-upload"
+
         # --- volume size
         _volsize=`_j_getvar ${STORAGEFILE} "duplicity_volsize"`
         test -z "$_volsize" && _volsize=`_j_getvar ${STORAGEFILE} "volsize"`
-
         if [ ! -z $_volsize ]; then
             echo -n " --volsize ${_volsize}"
         fi
 
-        # --- verbosity level to fetch changed files from log
-        echo -n " -v8"
-
-        # --- add asynchronous upload
-        echo -n " --asynchronous-upload"
-
-    }
-    # return a string with backup default params
-    function t_getParamBackup(){
-        echo -n ''
     }
     # return a cli parameter for a single exlude directory
     # param  string  cache directory for local index files
@@ -109,7 +101,7 @@ export PASSPHRASE
     }
 
 # --------------------------------------------------------------------------------
-# ACTIONS :: TRANSFER
+# BACKUP ACTIONS :: TRANSFER
 # --------------------------------------------------------------------------------
     # pre backup actions
     # uses global vars from ../../transfer.sh
@@ -125,7 +117,7 @@ export PASSPHRASE
     }
 
 # --------------------------------------------------------------------------------
-# GENERATE PARAMS :: SINGLE DIR
+# BACKUP ACTIONS :: SINGLE DIR
 # --------------------------------------------------------------------------------
 
     # get target url/ directory
@@ -137,22 +129,22 @@ export PASSPHRASE
 
     # get string with complete backup command
     function t_sd_getCmdBackup(){
-        echo duplicity ${sBackupParams} ${mydir} ${sTarget}
+        echo duplicity ${sBackupParams} ${mydir} ${STORAGE_TARGETPATH}
     }
 
     # pre backup tasks
     # uses global vars from ../../transfer.sh
     function t_sd_cmdPre(){
         # --- for rsync only: create remote directory
-        echo ${sTarget} | fgrep "rsync://"  >/dev/null
+        echo ${STORAGE_TARGETPATH} | fgrep "rsync://"  >/dev/null
         if [ $? -eq 0 ]; then
-          # sshTarget=`echo ${sTarget} | sed "s#rsync://#scp://#"`
+          # sshTarget=`echo ${STORAGE_TARGETPATH} | sed "s#rsync://#scp://#"`
           # echo Creating remote directory with fetching collection-status on $sshTarget
           # color cmd
           # duplicity collection-status ${sParams} ${sshTarget}
           # color reset
-          sshTarget=`echo ${sTarget} | cut -f 3 -d '/'`
-          RemoteDir=`echo ${sTarget} | cut -f 4- -d '/'`
+          sshTarget=`echo ${STORAGE_TARGETPATH} | cut -f 3 -d '/'`
+          RemoteDir=`echo ${STORAGE_TARGETPATH} | cut -f 4- -d '/'`
           cmd="ssh"
           if [ ! -z ${sFileSshPrivkey} ]; then
             cmd="${cmd} -i ${sFileSshPrivkey}"
@@ -179,7 +171,7 @@ export PASSPHRASE
             exit 1
         fi
 
-        cmd="duplicity remove-older-than $STORAGE_KEEP --force ${sParams} ${sTarget}"
+        cmd="duplicity remove-older-than $STORAGE_KEEP --force ${sParams} ${STORAGE_TARGETPATH}"
         echo $cmd
         color cmd
         $cmd
@@ -197,31 +189,97 @@ export PASSPHRASE
     # used in restore; directory param is checked before
     # param  string  name of backup dir, i.e. /etc
     function t_cmdShowVolumes(){
-        tmpoutVolumes=/tmp/outvolumelist_$$
-
-        echo duplicity collection-status ${sParams} ${sTarget}
-        color cmd
-        duplicity collection-status ${sParams} ${sTarget} | tee -a $tmpoutVolumes
-        fetchrc
-        color reset
-        echo
+        duplicity collection-status ${sParams} ${STORAGE_TARGETPATH}
+    }
 
-        if [ `cat $tmpoutVolumes | egrep "(Full|Incremental)" | wc -l` -eq 0 ]; then
+    # select a snapshot to restore from
+    function t_restoreSelect(){
+        local tmpoutVolumes=/tmp/outvolumelist_$$
+        local _date=
+        echo "--- Existing snapshots:"
+        t_cmdShowVolumes \
+            | grep -E "(Full|Incremental).*[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\ " \
+            | sort -u > $tmpoutVolumes
+        if [ `cat $tmpoutVolumes | wc -l` -eq 0 ]; then
             color error
-            echo "ERROR: no backup sets were found for directory [$sDir2restore]"
+            echo "ERROR: no backup sets were found for directory [$BACKUP_DIR]"
             echo
             color reset
-            sDir2restore=
+            BACKUP_DIR=
             setVars
         else
+            color cmd
+            cat $tmpoutVolumes
             color ok
-            echo "OK,  `cat $tmpoutVolumes | grep "Full" | wc -l` Full and  `cat $tmpoutVolumes | grep "Incremental" | wc -l` incremental backups"
+            echo "OK, `cat $tmpoutVolumes | grep "Full" | wc -l` Full and  `cat $tmpoutVolumes | grep "Incremental" | wc -l` incremental backups"
             color reset
         fi
 
         rm -f $tmpoutVolumes
+
+        echo
+
+        echo "The acceptible time strings are intervals (like \"3D64s\"), w3-datetime"
+        echo "strings, like \"2002-04-26T04:22:01-07:00\" (strings like"
+        echo "\"2002-04-26T04:22:01\" are also acceptable - duplicity will use the"
+        echo "current time zone), or ordinary dates like 2/4/1997 or 2001-04-23"
+        echo "(various combinations are acceptable, but the month always precedes"
+        echo "the day)."
+        echo
+        echo "today in YYYY-MM-DD: `date +%Y-%m-%d`"
+        echo 
+        showPrompt "[$RESTORE_ITEM] >"
+        read _date
+        test -z "$_date" && _date=$RESTORE_ITEM
+        RESTORE_ITEM=$_date
+        echo using \"$RESTORE_ITEM\"
+        # RESTORE_ITEMINFO=$( t_cmdShowVolumes | grep "^$RESTORE_ITEM" | awk '{ print $2 " " $3} ' )
+        RESTORE_ITEMINFO=
+        echo
+    }
+    # set a filter to reduce count of files to restore
+    function t_restoreFilter(){
+        local _inc=
+        echo "Enter a path behind ${BACKUP_DIR}/"
+        echo "empty means: all data"
+        echo 
+        showPrompt "[$RESTORE_FILTER] >"
+        read _inc
+
+        RESTORE_FILTER=
+        RESTORE_TARGETPATH="${RESTORE_BASEDIR}/${sSafeName}"
+        if [ ! -z "$_inc" ]; then
+            echo ${_inc} | grep '\*' >/dev/null
+            if [ $? -eq 0 ]; then
+                _inc=`dirname $_inc | sed 's#^\.##'`
+                color error
+                echo ERROR: using a placeholder is not allowed. Using the directory above.
+                echo [$_inc]
+                color reset
+            fi
+            RESTORE_FILTER="--file-to-restore $_inc"
+            RESTORE_TARGETPATH="${RESTORE_TARGETPATH}/${_inc}"
+        fi
+        echo using parameter \"$RESTORE_FILTER\"
+    }
+    # show stored volumes on backup repository
+    # used in restore; directory param is checked before
+    # param  string  name of backup dir, i.e. /etc
+    function t_cmdRestore(){
+        echo "duplicity restore $RESTORE_FILTER --time $RESTORE_ITEM ${sParams} ${STORAGE_TARGETPATH} ${RESTORE_TARGETPATH}"
+    }
+
+    # Mount backup data
+    function t_restoreDoMountBackupdata(){
+        echo "Mounting the backup data is not supported by Duplicity."
     }
 
+
+    # search a file in the given snapshot and backup dir
+    # param  string  regex to filter
+    function t_restoreDoSearchFile(){
+        eval restic ls ${sParams} --path "${BACKUP_DIR}" ${RESTORE_ITEM} | grep -E "$1"
+    }
 # --------------------------------------------------------------------------------
 # VERIFY RETURNCODES
 # --------------------------------------------------------------------------------
diff --git a/plugins/transfer/restic.sh b/plugins/transfer/restic.sh
index 9598f4a..6d588d4 100644
--- a/plugins/transfer/restic.sh
+++ b/plugins/transfer/restic.sh
@@ -10,21 +10,14 @@
 # 2021-05-19  ah    v0.0   INIT ... WIP
 # ================================================================================
 
-# --------------------------------------------------------------------------------
-# ENV VARS
-# export variables that are needed by the backup tool
-# --------------------------------------------------------------------------------
-
-# export PASSPHRASE
-
 # --------------------------------------------------------------------------------
 # INIT
 # --------------------------------------------------------------------------------
 
 
     function t_checkRequirements(){
-        j_requireUser "root"
         j_requireBinary "restic"
+        j_requireUser "root"
     }
 
     function t_setVars(){
@@ -38,8 +31,7 @@
         export GODEBUG="asyncpreemptoff=1"
 
         RESTORE_ITEM=latest
-        RESTORE_FILTER=
-        RESTORE_CMD=
+        RESTIC_MOUNTPOINT=$( _j_getvar ${STORAGEFILE} "restic_mountpoint")
     }
 
 # --------------------------------------------------------------------------------
@@ -54,7 +46,7 @@
         echo -n --verbose=$( _j_getvar ${STORAGEFILE} "restic_verbose")
 
     }
-    # return a string with backup default params
+    # return a string with backup parameters that will be added to defaults
     function t_getParamBackup(){
         # tagging
         echo -n --tag $( _j_getvar ${STORAGEFILE} "restic_tag")
@@ -101,7 +93,7 @@
     }
 
 # --------------------------------------------------------------------------------
-# ACTIONS :: TRANSFER
+# BACKUP ACTIONS :: TRANSFER
 # --------------------------------------------------------------------------------
     # pre backup actions
     # uses global vars from ../../transfer.sh
@@ -139,7 +131,9 @@
 
         echo "--- UNLOCK ... just in case :-)" 
         echo restic unlock ${sParams}
+        color cmd
         eval restic unlock ${sParams}
+        color reset
         echo
 
         echo "--- PRUNE"
@@ -171,7 +165,7 @@
     }
 
 # --------------------------------------------------------------------------------
-# ACTIONS :: SINGLE DIR
+# BACKUP ACTIONS :: SINGLE DIR
 # --------------------------------------------------------------------------------
 
     # get target url/ directory
@@ -208,7 +202,7 @@
     # used in restore; directory param is checked before
     # param  string  name of backup dir, i.e. /etc
     function t_cmdShowVolumes(){
-        eval restic snapshots ${sParams} --path $sDir2restore
+        eval restic snapshots ${sParams} --path ${BACKUP_DIR}
     }
 
     # select a snapshot to restore from
@@ -218,14 +212,24 @@
         color cmd
         t_cmdShowVolumes
         color reset
-        showPrompt "ID of the snapshot or \"latest\" to restore from [$RESTORE_ITEM] >"
+        showPrompt "ID of the snapshot or \"latest\" to restore from [${RESTORE_ITEM}] >"
         read _selid
-        test -z "$_selid" && _selid=$RESTORE_ITEM
-        RESTORE_ITEM=$_selid
-        echo using \"$RESTORE_ITEM\"
-        RESTORE_ITEMINFO=$( t_cmdShowVolumes | grep "^$RESTORE_ITEM" | awk '{ print $2 " " $3} ' )
+        test -z "$_selid" && _selid=${RESTORE_ITEM}
+        RESTORE_ITEM=${_selid}
+
+        test "$RESTORE_ITEM" = "latest" && RESTORE_ITEMINFO="automatic value"
+        test "$RESTORE_ITEM" = "latest" || RESTORE_ITEMINFO=$( t_cmdShowVolumes | grep "^${RESTORE_ITEM} " | awk '{ print $2 " " $3} ' )
+
+        if [ -z "${RESTORE_ITEMINFO}" ]; then
+            color error
+            echo ERROR: A napshot ID \"${_selid}\" does not exist.
+            RESTORE_ITEM=latest
+            color reset
+        fi
+        echo using \"${RESTORE_ITEM}\"
         echo
     }
+
     # set a filter to reduce count of files to restore
     function t_restoreFilter(){
         local _inc=
@@ -233,17 +237,42 @@
         echo "  - a single directory name anywhere in the folderstructure"
         echo "  - a filename without path"
         echo "  - a filemask"
-        showPrompt "Include []>"
+        showPrompt "Include >"
         read _inc
-        RESTORE_FILTER="$_sIncParams $( t_getParamInlude "$_inc" )"
-        echo using parameter \"$RESTORE_FILTER\"
+        RESTORE_FILTER="$( t_getParamInlude "${_inc}" )"
+        echo using parameter \"${RESTORE_FILTER}\"
         echo
     }
     # show stored volumes on backup repository
     # used in restore; directory param is checked before
     # param  string  name of backup dir, i.e. /etc
     function t_cmdRestore(){
-        echo "eval restic restore ${sParams} --path $sDir2restore --target ${sRestorepath} $RESTORE_FILTER $RESTORE_ITEM"
+        echo "eval restic restore ${sParams} --path ${BACKUP_DIR} --target ${RESTORE_TARGETPATH} ${RESTORE_FILTER} ${RESTORE_ITEM}"
+    }
+
+    # Mount backup data
+    function t_restoreDoMountBackupdata(){
+        local _cmd=
+        echo HINT: This feature requires fuse. It works on UNIX/ LINUX platforms - not on MS Windows.
+        echo
+        if [ -z "$RESTIC_MOUNTPOINT" ]; then
+            color error
+            echo "ERROR: no mountpoint was set in ${STORAGEFILE}; example: restic_mountpoint = /mnt/restore"
+            color reset
+        else
+            _cmd="restic mount ${sParams} $RESTIC_MOUNTPOINT"
+            test -z "${BACKUP_DIR}" || _cmd="restic mount ${sParams} --path ${BACKUP_DIR} $RESTIC_MOUNTPOINT"
+            echo $_cmd
+            color cmd
+            eval $_cmd
+            color reset
+        fi
+    }
+
+    # search a file in the given snapshot and backup dir
+    # param  string  regex to filter
+    function t_restoreDoSearchFile(){
+        eval restic ls ${sParams} --path "${BACKUP_DIR}" ${RESTORE_ITEM} | grep -E "$1"
     }
 
 # --------------------------------------------------------------------------------
diff --git a/restore.sh b/restore.sh
index 1f5a67e..0fe1c47 100755
--- a/restore.sh
+++ b/restore.sh
@@ -34,14 +34,16 @@
   . `dirname $0`/jobhelper.sh
   . `dirname $0`/inc_bash.sh
 
+  # --- load a transfer plugin
   STORAGE_BIN=`_j_getvar ${STORAGEFILE} "bin"`
   if [ -z "$STORAGE_BIN" ]; then
-    STORAGE_BIN=restic
-    # STORAGE_BIN=duplicity
+    # STORAGE_BIN=restic
+    STORAGE_BIN=duplicity
   fi
 
   . `dirname $0`/plugins/transfer/$STORAGE_BIN.sh || exit 1
 
+  # --- get backend url of backup data
   STORAGE_BASEDIR=`_j_getvar ${STORAGEFILE} "storage"`
   if [ -z $STORAGE_BASEDIR ]; then
     echo ERROR: missing config for backup target.
@@ -49,36 +51,42 @@
     exit 1
   fi
 
+  # target directory of directory specific repository
+  STORAGE_TARGETPATH=
 
+  PASSPHRASE=`_j_getvar ${STORAGEFILE} "passphrase"`
+
+  # timestamp or snapshot id
+  RESTORE_ITEM=
 
-  # ----- read something from config files
+  # include filter to restore a part of the backup set
+  RESTORE_FILTER=
+
+  # full path of restore data
   RESTORE_BASEDIR=`_j_getvar ${STORAGEFILE} "restore-path"`
-  PASSPHRASE=`_j_getvar ${STORAGEFILE} "passphrase"`
-  export PASSPHRASE
+  RESTORE_TARGETPATH=
 
+  # set vars for transfer plugin
   t_setVars || exit 1
 
-  # ----- init default vars
-  sParams="$( t_getParamDefault $1 $2 )"
-  sFileSshPrivkey=`_j_getvar ${STORAGEFILE} "ssh-privatekey"`
-  if [ ! -z $sFileSshPrivkey ]; then
-    sParams="${sParams} $( t_getParamSshKey $sFileSshPrivkey )"
-  fi
+
+  # ----- Create default command line parameters
+    sParams="$( t_getParamDefault $1 $2 )"
+    sFileSshPrivkey=`_j_getvar ${STORAGEFILE} "ssh-privatekey"`
+    if [ ! -z $sFileSshPrivkey ]; then
+      sParams="${sParams} $( t_getParamSshKey $sFileSshPrivkey )"
+    fi
 
 
-  # task#3046 - add custom cache dir
-  sCacheDir=`_j_getvar ${STORAGEFILE} "cachedir"`
-  if [ ! -z $sCacheDir ]; then
+    # task#3046 - add custom cache dir
+    sCacheDir=`_j_getvar ${STORAGEFILE} "cachedir"`
     sParams="${sParams} $( t_getParamCacheDir $sCacheDir )"
-  fi
+
 
   # ----- what to restore ...
-  sDir2restore= 
-  sRestoreItem=
-  sDate=`date +%Y-%m-%d`
+  BACKUP_DIR= 
+
 
-  # target directory of directory specifi repository
-  sTarget=
 
 # --------------------------------------------------------------------------------
 # FUNCTIONS
@@ -111,7 +119,7 @@ function enterBackupDir(){
   done
 
   color input
-  echo -n "[$sDir2restore] >"
+  echo -n "[$BACKUP_DIR] >"
   color reset
   read myinput
 
@@ -147,7 +155,7 @@ function setBackupDir(){
 
     else
 
-      sDir2restore=$1
+      BACKUP_DIR=$1
       setVars
     fi
   fi
@@ -156,40 +164,41 @@ function setBackupDir(){
 # ----------------------------------------------------------------------
 # internal: set variables for target path and backup set 
 # ----------------------------------------------------------------------
-function setVars(){
-  
-  sSafeName=`j_getSafename "$sDir2restore"`
-  sTarget="$( t_sd_getTarget $sDir2restore )"
-  # sTarget=`j_getFullTarget "$sDir2restore"`
 
-  sRestorepath="${RESTORE_BASEDIR}/${sSafeName}"
+# set backup url and local restore path (based on given backup directory)
+function setVars(){
+  local sSafeName=`j_getSafename "$BACKUP_DIR"`
+  RESTORE_TARGETPATH="${RESTORE_BASEDIR}/${sSafeName}"
+  STORAGE_TARGETPATH="$( t_sd_getTarget $BACKUP_DIR )"
 }
 
+# actions for restore
 function doRestore(){
-  restorecmd=$( t_cmdRestore )
+  local restorecmd=$( t_cmdRestore )
   if [ -z "$restorecmd" ]; then
     color error
-    echo "ERROR: no restore command ... "
-    echo "A developer must check t_inputs4Restore and t_cmdRestore in plugins/transfer/$STORAGE_BIN.sh"
+    echo "ERROR: There is no restore command ... "
+    echo "A developer must check t_cmdRestore in plugins/transfer/$STORAGE_BIN.sh"
     color reset
     exit 1
   fi
 
-  mkdir -p "${sRestorepath}"
+  mkdir -p "${RESTORE_TARGETPATH}"
+  echo $restorecmd
   color cmd
   $restorecmd
   fetchrc
   color reset
 
-  t_rcCheckRestore
+  t_rcCheckRestore $myrc
 
   echo
   echo
   echo Restore is finished.
   echo Have look to the output above.
-  echo "The restore path has `find ${sRestorepath} -type f | wc -l` files (`du -hs ${sRestorepath} | awk '{ print $1 }'`)"
+  echo "The restore path has `find ${RESTORE_TARGETPATH} | wc -l` items (`du -hs ${RESTORE_TARGETPATH} | awk '{ print $1 }'`)"
   echo 
-  echo find ${sRestorepath}
+  echo find ${RESTORE_TARGETPATH}
   exit
 
 }
@@ -204,7 +213,7 @@ function doRestore(){
   t_checkRequirements
 
   setBackupDir $1
-  if [ -z $sDir2restore ]; then
+  if [ -z $BACKUP_DIR ]; then
     enterBackupDir
   fi
 
@@ -216,30 +225,27 @@ function doRestore(){
 
     h1 "Restore :: Menu"
 
-    # getRemoteVolumes
-    # getRemoteFiles
-
-    echo
-    echo " D - directory to restore: $sDir2restore"
+    echo " D - directory to restore: $BACKUP_DIR"
     echo -n " W - time or snapshot ID : $RESTORE_ITEM"
-      test -z "$RESTORE_ITEM" && echo -n " ... set it"
+      test -z "$RESTORE_ITEM" && echo -n " ... set one first"
       test -z "$RESTORE_ITEMINFO" || echo -n " ($RESTORE_ITEMINFO)"
       echo
     echo -n " F - what to restore     : $RESTORE_FILTER"
       test -z "$RESTORE_FILTER" && echo -n "(no filter = restore all files)"
       echo
     echo
+    echo " M - mount backup"
     # echo " C - show file changes"
     # echo " S - search file"
     # echo " V - verify"
     # echo " B - Bash (Shell)"
     # echo
-    echo " R - start restore"
+    echo " R - start restore with $STORAGE_BIN"
     echo
-    echo "     restore from         : $sTarget"
-    echo "     restore to           : $sRestorepath"
+    echo "     restore from         : $STORAGE_TARGETPATH"
+    echo "     restore to           : $RESTORE_TARGETPATH"
     echo -n "                            "
-    ls -d $sRestorepath >/dev/null 2>&1
+    ls -d $RESTORE_TARGETPATH >/dev/null 2>&1
     if [ $? -eq 0 ]; then
       color error
       echo "WARNING: directory already exists! Backup will fail."
@@ -266,13 +272,22 @@ function doRestore(){
       c|C)
         showFilechanges
         ;;
+      m|M)
+        h2 "Mount backup data"
+        t_restoreDoMountBackupdata
+        ;;
       s|S)
-        searchFile
+        h2 "Search a file"
+        filefilter=".*"
+        showPrompt "Regex for filefilter; ${filefilter} for all >"
+        read filefilter
+        test -z "${filefilter}" || t_restoreDoSearchFile "${filefilter}"
         ;;
       v|V)
         verify
         ;;
       b|B)
+        h2 "Shell"
         echo type exit to return...
         export PS1="[`basename $0` \u@\h \w]\$ "
         bash
diff --git a/transfer.sh b/transfer.sh
index 48e8cbc..2d455cd 100755
--- a/transfer.sh
+++ b/transfer.sh
@@ -54,14 +54,14 @@
 
   # check
   if [ -z "$STORAGE_BIN" ]; then
-    STORAGE_BIN=restic
-    # STORAGE_BIN=duplicity
+    # STORAGE_BIN=restic
+    STORAGE_BIN=duplicity
   fi
 
   if [ -z "$STORAGE_BASEDIR" ]; then
     color error
     echo ERROR: missing config for backup target.
-    echo There must be an entry storage in ${STORAGEFILE}
+    echo There must be an entry "storage = " in ${STORAGEFILE}
     color reset
     exit 1
   fi
@@ -104,12 +104,12 @@
 
 
   
-  h1 `date` TRANSFER LOCAL DATA TO STORAGE                                            | tee -a $transferlog
+  h1 `date` TRANSFER LOCAL DATA TO STORAGE                                             | tee -a $transferlog
   
-  echo METHOD: $METHOD                                                                | tee -a $transferlog
-  echo TARGET: ${STORAGE_BASEDIR}                                                     | tee -a $transferlog
-  echo TOOL  : $STORAGE_BIN                                                           | tee -a $transferlog
-  echo                                                                                | tee -a $transferlog
+  echo "METHOD: $METHOD"                                                               | tee -a $transferlog
+  echo "TARGET: ${STORAGE_BASEDIR}"                                                    | tee -a $transferlog
+  echo "TOOL  : $STORAGE_BIN"                                                          | tee -a $transferlog
+  echo                                                                                 | tee -a $transferlog
 
   . `dirname $0`/plugins/transfer/$STORAGE_BIN.sh || exit 1
 
-- 
GitLab