#!/bin/bash
################################################################################
#                                                                              #
#                          SD-Copy | Simple Disk Copy                          #
#        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~        #
#          Simple Shell-Frontend for ocs-onthefly (Clonezilla) and dd          #
#                                                                              #
#                       (C)opyright bei Michael Gasbers                        #
#                             All rights reserved                              #
#                                                                              #
################################################################################
#                                                                              #
#  DIESE SOFTWARE WIRD OHNE MÄNGELGEWÄHR UND OHNE JEGLICHE AUSDRÜCKLICHE ODER  #
#  STILLSCHWEIGENDE GARANTIE ZUR VERFÜGUNG GESTELLT, EINSCHLIESSLICH UND OHNE  #
#  EINSCHRÄNKUNG JEGLICHER GARANTIE FÜR DIE GEBRAUCHSTAUGLICHKEIT ODER EIGNUNG #
#  FÜR EINEN BESTIMMTEN ZWECK. ALLE RISIKEN IN BEZUG AUF ERGEBNISSE UND        #
#  LEISTUNG DIESER SOFTWARE WERDEN VOLLSTÄNDIG VOM BENUTZER ÜBERNOMMEN!        #
#  --------------------------------------------------------------------------  #
#  THIS SOFTWARE IS PROVIDED "AS IS" WITH NO WARRANTIES WHAT SO EVER, WHETHER  #
#  EXPRESSED OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF       #
#  USABILITY OR FITNESS FOR A PARTICULAR PURPOSE. ALL RISKS CONCERNING RESULTS #
#  AND PERFORMANCE OF THIS SOFTWARE ARE ASSUMED COMPLETELY BY THE USER!        #
#                                                                              #
################################################################################
#                                                                              #
#  Jegliche Form der Kopie, Veränderung und Verwendung dieses Skripts sowie    #
#  Teilen davon ist nur für rein private Zwecke erlaubt. Insbesondere eine     #
#  Nutzung und Verbreitung für kommerzielle Zwecke ist strengstens verboten!   #
#  --------------------------------------------------------------------------  #
#  Any form of copying, modification and use of this script and parts thereof  #
#  is only permitted for purely private purposes. In particular, any use and   #
#  distribution for commercial purposes is strictly prohibited!                #
#                                                                              #
################################################################################
#                                                                              #
#  Dies und andere Tools sind auch zu finden auf: https://github.com/migacode  #
#  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  #
#   Für Anregungen und Fragen zu diesem Tool bitte Kontakt mit uns aufnehmen   #
#   über https://migano.de oder per E-Mail an kontakt@migano.de. Danke.        #
#                                                                              #
################################################################################
# Letzte Änderung: 15.01.2026
VERSION="1.75"

################################################################################
#                                                                              #
#           Bei unzureichenden Zugriffsrechten mit sudo durchstarten           #
#                                                                              #
################################################################################
if [ $(id -u) -ne 0 ]; then
   sudo -kK
   sudo --preserve-env=XDG_SESSION_TYPE "$0" "$@"
   exit 0
fi

################################################################################
#                                                                              #
#                            Funktionen definieren                             #
#                                                                              #
################################################################################
#===============================================================================
# Einfache Ja/Nein-Abfrage
# -------------------------
# Parameter $1: Anzuzeigender Text
# Parameter $2: Antwort-Vorgabe / Default (optional)
# -----------
# Rückgaben:
# 0 = false (Nein)
# 1 = true (Ja)
#===============================================================================
function ask_yes_or_no {
  echo -e -n " $1 [${bold_yellow}"
  if [ "$2" == "J" ] || [ "$2" == "j" ];
  then
    echo -e -n "J"
  else
    echo -e -n "j"
  fi
  echo -e -n "${colors_off}]a oder [${bold_yellow}"
  if [ "$2" == "N" ] || [ "$2" == "n" ];
  then
    echo -e -n "N"
  else
    echo -e -n "n"
  fi
  echo -e -n "${colors_off}]ein? "
  IYN_RESULT=0
  ANSWER=""
  while [ "$ANSWER" == "" ];
  do
    read -N 1 -r -s ANSWER
    if [ "$ANSWER" == $'\n' ]; then ANSWER="$2"; fi
    ANSWER=$(echo ${ANSWER} | sed 's/[^JjNn]*//g')
  done
  echo -e "$ANSWER"
  if [ "$ANSWER" == "J" ] ||
     [ "$ANSWER" == "j" ];
  then
    IYN_RESULT=1
  fi
  return $IYN_RESULT
}

#===============================================================================
# Erstellung eines Starters auf dem Desktop und im Anwendungs-Menü
# Parameter $1: Einschließlich der Kommandozeilen-Optionen (1) oder ohne (0)
#===============================================================================
function create_starter {
  STARTER_FILE="$DESKTOP_DIR/$SCRIPT_NAME"
  STARTER_NAME="SD-Copy"
  SCRIPT_CALL="$SCRIPT_NAME"
  if [ $1 -eq 1 ];
  then
    STARTER_NAME+=" ("
    # automode
    if [ $AUTOMATIC_MODE -eq 1 ];
    then
      STARTER_FILE+="_a"
      STARTER_NAME+="a"
      SCRIPT_CALL+=" -a"
    fi
    # bootonly
    if [ $BOOTSECTOR_ONLY -eq 1 ];
    then
      STARTER_FILE+="_b"
      STARTER_NAME+="b"
      SCRIPT_CALL+=" -b"
    fi
    # deepmode
    if [ $USE_DEEPMODE -eq 1 ];
    then
      STARTER_FILE+="_d"
      STARTER_NAME+="d"
      SCRIPT_CALL+=" -d"
    fi
    # noupdate
    if [ $CHECK_UPDATE -eq 0 ];
    then
      STARTER_FILE+="_n"
      STARTER_NAME+="n"
      SCRIPT_CALL+=" -n"
    fi
    # ocsmode
    if [ $USE_OCSMODE -eq 1 ];
    then
      STARTER_FILE+="_o"
      STARTER_NAME+="o"
      SCRIPT_CALL+=" -o"
    fi
    # noboots
    if [ $NO_BOOTSECTOR -eq 1 ];
    then
      STARTER_FILE+="_t"
      STARTER_NAME+="t"
      SCRIPT_CALL+=" -t"
    fi
    STARTER_NAME+=")"
  fi
  STARTER_FILE+=".desktop"
  echo -e -n " Erstelle Starter ... "
  echo -e "[Desktop Entry]" > "$STARTER_FILE" 2>/dev/null
  if [ $? -eq 0 ];
  then
    # ------------------
    # Starter erstellen
    # ------------------
    echo -e "Type=Application" >> "$STARTER_FILE" 2>/dev/null
    echo -e "Name=$STARTER_NAME" >> "$STARTER_FILE" 2>/dev/null
    echo -e "Comment=Simple Disk Copy im Terminal starten" >> "$STARTER_FILE" 2>/dev/null
    echo -e "Exec=bash -c 'cd $SCRIPT_PATH && sudo ./$SCRIPT_CALL;\$SHELL'" >> "$STARTER_FILE" 2>/dev/null
    echo -e "Icon=sd-copy" >> "$STARTER_FILE" 2>/dev/null
    echo -e "Categories=Application;" >> "$STARTER_FILE" 2>/dev/null
    echo -e "Terminal=true" >> "$STARTER_FILE" 2>/dev/null
    echo -e "StartupNotify=true" >> "$STARTER_FILE" 2>/dev/null
    echo -e "NoDisplay=false" >> "$STARTER_FILE" 2>/dev/null
    chown -R "$USER_USERNAME:$USER_USERNAME" "$STARTER_FILE" &>/dev/null
    chmod -R 0755 "$STARTER_FILE" &>/dev/null
    # --------------------------------
    # Icon für den Starter downloaden
    # --------------------------------
    download_icon_file "sd-copy"
    echo -e "$OK_TAG"
    # --------------------------------------------------------------------------
    # Zuvor erstellten Starter für uns selbst auch im System-Menü anlegen
    # --------------------------------------------------------------------------
    # Auf diese Art, damit die vom System automatisch eingefügten Steuerzeichen
    # dabei entfernt werden, da Letztere die Menü-Darstellung unterbinden.
    # --------------------------------------------------------------------------
    STARTMENU_DIR="$USER_HOME_DIR/.local/share/applications"
    STARTMENU_FILE="$STARTMENU_DIR/${STARTER_FILE##*/}"
    if [ -s "$STARTER_FILE" ] &&
       [ -d "$STARTMENU_DIR" ] &&
       [ ! -s "$STARTMENU_FILE" ];
    then
      cat "$STARTER_FILE" | tr -dc '[:print:]\n' > "$STARTMENU_FILE" 2>/dev/null
      sed -i -E "s/\\\n\(Terminal\)//i" "$STARTMENU_FILE"
      chown -R "$USER_USERNAME:$USER_USERNAME" "$STARTMENU_FILE" &>/dev/null
      chmod -R 0644 "$STARTMENU_FILE" &>/dev/null
    fi
  else
    echo -e "$ERROR_TAG"
  fi
}

#===============================================================================
# Download einer Bild-Datei (Pixmap)
# -----------------------------------
# Parameter $1: Dateiname (ohne Endung)
#===============================================================================
function download_icon_file {
  PKG_PICTURE_NAME="$1.png"
  PKG_PICTURE_DIR="/usr/share/pixmaps"
  PKG_PICTURE_FILE="$PKG_PICTURE_DIR/$PKG_PICTURE_NAME"
  if [ -d "$PKG_PICTURE_DIR" ] &&
     [ ! -s "$PKG_PICTURE_FILE" ];
  then
    PKG_PICTURE_URL="$RESSOURCE_SERVER_DIR/png/$PKG_PICTURE_NAME"
    LOCAL_DOWNLOAD_FILE="$DOWNLOAD_DIR/$PKG_PICTURE_NAME"
    wget -nv -O "$LOCAL_DOWNLOAD_FILE" "$PKG_PICTURE_URL" &>/dev/null
    DOWNLOAD_RESULT=$?
    if [ $DOWNLOAD_RESULT -eq 0 ] &&
       [ -s "$LOCAL_DOWNLOAD_FILE" ] &&
       [ $(grep -i -c -E "Error\s*404" "$LOCAL_DOWNLOAD_FILE") -eq 0 ];
    then
      mv -f "$LOCAL_DOWNLOAD_FILE" "$PKG_PICTURE_FILE" &>/dev/null
      chown -R "root:root" "$PKG_PICTURE_FILE" &>/dev/null
      chmod -R 0644 "$PKG_PICTURE_FILE" &>/dev/null
    else
      remove_file "$LOCAL_DOWNLOAD_FILE"
    fi
  fi
}

#===============================================================================
# Erstellung einer Liste aller Disk-Devices oder wahlweise die Ermittlung nur
# des ersten neuen "Buchstabens"
# -------------------------------
# Parameter $1:
# 0 = Vollständige neue Liste erstellen (wird in device_list gespeichert)
# 1 = Nur ersten neuen "Buchstaben" finden (wird in first_new_char gespeichert)
#===============================================================================
function get_disk_letter {
  get_only_first_new=$1
  first_new_char=""
  devices_in_list=${#device_list[@]}
  device_chars_list=({a..z})
  for device_char in ${device_chars_list[@]};
  do
    if [ $get_only_first_new -ne 1 ] ||
       [ "$first_new_char" == "" ];
    then
      if [ "sd${device_char}" != "$boot_device" ] &&
         [ -b "/dev/sd${device_char}" ];
         # Alternativ: Nur gemountete erkennen >= "/dev/sd${device_char}1"
      then
        already_exists=0
        c=0
        while [ $c -lt $devices_in_list ] &&
              [ $already_exists -eq 0 ];
        do
          if [ "${device_char}" == "${device_list[$c]}" ];
          then
            already_exists=1
          fi
          ((c+=1))
        done
        if [ $already_exists -eq 0 ];
        then
          TEST_CAPACITY=$(show_disk_info "sd$device_char" 1 20 1)
          if [ "$TEST_CAPACITY" != "" ] &&
             [ "$TEST_CAPACITY" != "0" ];
          then
            first_new_char="$device_char"
            device_list[${devices_in_list}]="$device_char"
            devices_in_list=${#device_list[@]}
          else
            eject "/dev/sd$device_char" &>/dev/null
          fi
        fi
      fi
    fi
  done
}

#===============================================================================
# Versionsnummer der Form X.Y.Z in nummerischen Wert umwandeln
#===============================================================================
function get_version_value {
  THE_VERSION=$(echo -n ${1} | sed "s/[^0-9\.]//g" | xargs 2>/dev/null)
  VERSION_PART_1=$(echo ${THE_VERSION} | cut -d '.' -f 1 | xargs 2>/dev/null)
  if [ "$VERSION_PART_1" == "" ]; then VERSION_PART_1="00"; fi
  VERSION_PART_2=$(echo ${THE_VERSION} | cut -d '.' -f 2 | xargs 2>/dev/null)
  if [ "$VERSION_PART_2" == "" ]; then VERSION_PART_2="00"; fi
  VERSION_PART_3=$(echo ${THE_VERSION} | cut -d '.' -f 3 | xargs 2>/dev/null)
  if [ "$VERSION_PART_3" == "" ]; then VERSION_PART_3="00"; fi
  VERSION_VALUE=$(((${VERSION_PART_1:0:2}*10000)+(${VERSION_PART_2:0:2}*100)+(${VERSION_PART_3:0:2})))
  echo -n "$VERSION_VALUE"
}

#===============================================================================
# Einfügung von Leerzeichen
# --------------------------
# Parameter $1: Anzahl
#===============================================================================
function insert_spaces {
  i=1
  while [ $i -le $1 ];
  do
    echo -e -n " "
    ((i+=1))
  done
}

#===============================================================================
# Löschen einer bestimmten einzelnen Datei
#===============================================================================
function remove_file {
  if [ "$1" != "" ] &&
     [ -f "$1" ];
  then
    rm -f "$1" &>/dev/null
  fi
}

#===============================================================================
# Ermittlung und Anzeige der Hardware-Informationen zu einer Disk
# ----------------------------------------------------------------
# Parameter $1: Device-Name (ohne Pfad, bspw. sda)
# Parameter $2: Kapazität anzeigen (1) oder nicht (0)
# Parameter $3: Maximale Länge jeder Teil-Zeichenfolge
# Parameter $4: Keine Infos anzeigen, nur Kapazität als Wert zurückgeben (1)
#===============================================================================
function show_disk_info {
  DEVICE_NAME="/dev/$1"
  SHOW_CAPACITY="$2"
  if [ "$SHOW_CAPACITY" == "" ]; then SHOW_CAPACITY=0; fi
  MAX_INFO_LENGTH="$3"
  if [ "$MAX_INFO_LENGTH" == "" ]; then MAX_INFO_LENGTH=24; fi
  ONLY_CAPACITY=$4
  #-----------------------------------------------------------------------------
  # Ausgeworfene Geräte neu verbinden um alle Informationen auslesen zu können
  #-----------------------------------------------------------------------------
  DEVICE_RECONNECTED=0
  if [ "${DEVICE_NAME}" != "/dev/$boot_device" ] &&
     [ $(ls -la ${DEVICE_NAME}* 2>/dev/null | wc -l ) -eq 1 ];
  then
    eject -t ${DEVICE_NAME} &>/dev/null
    if [ $? -eq 0 ];
    then
      DEVICE_RECONNECTED=1
    fi
  fi
  # --------------------------------
  # Hersteller (Family / Vendor)
  # --------------------------------
  # lsblk
  DISK_FAMILY=$(LANG=en lsblk -d -n -o vendor ${DEVICE_NAME} 2>/dev/null | head -n 1 | sed -E "s/[\"\']//g" | xargs 2>/dev/null)
  # smartctl (1)
  if [ "$DISK_FAMILY" == "" ] || [ "$DISK_FAMILY" == "ATA" ] || [ "$DISK_FAMILY" == "USB" ];
  then
    DISK_FAMILY=$(LANG=en smartctl -x -d sat,auto ${DEVICE_NAME} 2>/dev/null | grep -i -E "^\s*vendor\s*:" | sed -E "s/[\"\']//g" | cut -d":" -f 2 | xargs 2>/dev/null)
  fi
  # smartctl (2)
  if [ "$DISK_FAMILY" == "" ] || [ "$DISK_FAMILY" == "ATA" ] || [ "$DISK_FAMILY" == "USB" ];
  then
    DISK_FAMILY=$(LANG=en smartctl -x -d sat,auto ${DEVICE_NAME} 2>/dev/null | grep -i -E "^s*model\s*family\s*:" | sed -E "s/[\"\']//g" | cut -d":" -f 2 | xargs 2>/dev/null)
  fi
  # Ausgabe bereinigen
  DISK_FAMILY=$(echo ${DISK_FAMILY//_/ } | sed -E "s/^ATA\s*//" | sed -E "s/^USB\s*//" | xargs 2>/dev/null)
  if [ ${#DISK_FAMILY} -gt $MAX_INFO_LENGTH ]; then DISK_FAMILY=${DISK_FAMILY:0:$MAX_INFO_LENGTH}; fi
  # --------------------------------
  # Bezeichnung (Model)
  # --------------------------------
  # lsblk
  DISK_MODEL=$(LANG=en lsblk -d -n -o model ${DEVICE_NAME} 2>/dev/null | head -n 1 | sed -E "s/[\"\']//g" | xargs 2>/dev/null)
  # smartctl (1)
  if [ "$DISK_MODEL" == "" ];
  then
    DISK_MODEL=$(LANG=en smartctl -x -d sat,auto ${DEVICE_NAME} 2>/dev/null | grep -i -E "^\s*device\s*model\s*:" | sed -E "s/[\"\']//g" | cut -d":" -f 2 | xargs 2>/dev/null)
  fi
  # smartctl (2)
  if [ "$DISK_MODEL" == "" ];
  then
    DISK_MODEL=$(LANG=en smartctl -x -d sat,auto ${DEVICE_NAME} 2>/dev/null | grep -i -E "^\s*product\s*:" | sed -E "s/[\"\']//g" | cut -d":" -f 2 | xargs 2>/dev/null)
  fi
  # parted
  if [ "$DISK_MODEL" == "" ];
  then
    DISK_MODEL=$(LANG=en parted -s ${DEVICE_NAME} print 2>/dev/null | grep -i -E "^\s*model\s*:" | sed -E "s/[\"\']//g" | cut -d":" -f 2 | xargs 2>/dev/null)
  fi
  # udevadm
  if [ "$DISK_MODEL" == "" ];
  then
    if udevadm --version &>/dev/null;
    then
      DISK_MODEL=$(LANG=en udevadm info --name=${DEVICE_NAME} 2>/dev/null | grep -i -E ".*id_model=" | sed -E "s/[\"\']//g" | cut -d"=" -f 2 | xargs 2>/dev/null)
    fi
  fi
  # Ausgabe bereinigen
  DISK_MODEL=$(echo ${DISK_MODEL//_/ } | sed -E "s/^ATA\s*//" | sed -E "s/^USB\s*//" | xargs 2>/dev/null)
  if [ ${#DISK_MODEL} -gt $MAX_INFO_LENGTH ]; then DISK_MODEL=${DISK_MODEL:0:$MAX_INFO_LENGTH}; fi
  # --------------------------------
  # Seriennummer (Serial)
  # --------------------------------
  # lsblk
  DISK_SERIAL=$(LANG=en lsblk -d -n -o serial ${DEVICE_NAME} 2>/dev/null | head -n 1 | sed -E "s/[\"\']//g" | xargs 2>/dev/null)
  # smartctl
  if [ ${#DISK_SERIAL} -lt 5 ];
  then
    DISK_SERIAL=$(LANG=en smartctl -x -d sat,auto ${DEVICE_NAME} 2>/dev/null | grep -i -E "^\s*serial\s*number\s*:" | sed -E "s/[\"\']//g" | cut -d":" -f 2| xargs 2>/dev/null)
  fi
  # udevadm
  if [ ${#DISK_SERIAL} -lt 5 ];
  then
    if udevadm --version &>/dev/null;
    then
      DISK_SERIAL=$(LANG=en udevadm info --name=${DEVICE_NAME} 2>/dev/null | grep -i -E "\s*E:\s*ID_SERIAL_SHORT\s*=" | head -n 1 | sed -E "s/[\"\']//g" | sed -E "s/\s*E:\s*ID_SERIAL_SHORT\s*=//i" | xargs 2>/dev/null)
    fi
  fi
  # Ausgabe bereinigen
  DISK_SERIAL=$(echo ${DISK_SERIAL//_/ } | xargs 2>/dev/null)
  if [ ${#DISK_SERIAL} -gt $MAX_INFO_LENGTH ]; then DISK_SERIAL="~${DISK_SERIAL:(-$MAX_INFO_LENGTH):$MAX_INFO_LENGTH}"; fi
  # --------------------------------
  # Kapazität
  # --------------------------------
  NUMBER_HAS_FORMAT=0
  # lsblk
  DISK_CAPACITY=$(LANG=en lsblk -d -n -o size ${DEVICE_NAME} 2>/dev/null | head -n 1 | sed -E "s/[\"\']//g" | xargs 2>/dev/null)
  # smartctl
  if [ "$DISK_CAPACITY" == "" ];
  then
    DISK_CAPACITY=$(LANG=en smartctl -x -d sat,auto ${DEVICE_NAME} 2>/dev/null | grep -i -E "^\s*user\s*capacity\s*:" | sed -E "s/[\"\']//g" | cut -d ":" -f 2 | awk '{print $1}' | sed "s/[^0-9]//g" | xargs 2>/dev/null)
  fi
  # parted
  if [ "$DISK_CAPACITY" == "" ];
  then
    DISK_CAPACITY=$(LANG=en parted -s ${DEVICE_NAME} print 2>/dev/null | grep -i -E "^Disk ${DEVICE_NAME}" | sed -E "s/[\"\']//g" | cut -d":" -f 2 | xargs 2>/dev/null)
  fi
  # Wenn die Ausgabe schon formatiert ist, diese nicht mehr neu formatieren
  if [ $(echo ${DISK_CAPACITY} | grep -c -i -E "[BKMGT]") -gt 0 ]; then NUMBER_HAS_FORMAT=1; fi
  if [ $NUMBER_HAS_FORMAT -eq 0 ] &&
     [ "$DISK_CAPACITY" != "" ];
  then
    DISK_SIZE=$(show_human_bytes ${DISK_CAPACITY} "M")
    if [ ${#DISK_SIZE} -gt 7 ];
    then
      DISK_SIZE=$(show_human_bytes ${DISK_CAPACITY} "G")
    fi
  else
    DISK_SIZE="$DISK_CAPACITY"
  fi
  if [ "$DISK_SIZE" == "0" ] ||
     [ "$DISK_SIZE" == "0B" ];
  then
    DISK_SIZE=""
  fi
  DISK_CAPACITY="$DISK_SIZE"
  # Ausgabe bereinigen
  if [ ${#DISK_CAPACITY} -gt $MAX_INFO_LENGTH ]; then DISK_CAPACITY=${DISK_CAPACITY:0:$MAX_INFO_LENGTH}; fi
  #-----------------------------------------------------------------------------
  # Vormals ausgeworfene und durch uns neu verbundene Geräte wieder auswerfen,
  # sofern diese nicht brauchbar sind
  #-----------------------------------------------------------------------------
  if [ $DEVICE_RECONNECTED -eq 1 ];
  then
    if [ "$DISK_CAPACITY" == "" ] ||
       [ "$DISK_CAPACITY" == "0" ];
    then
      eject ${DEVICE_NAME} &>/dev/null
    fi
  fi
  # ------------------
  # Start der Ausgabe
  # ------------------
  if [ $ONLY_CAPACITY -eq 1 ];
  then
    echo -e -n "$DISK_CAPACITY"
  else
    if [ "$DISK_FAMILY" != "" ] ||
       [ "$DISK_MODEL"  != "" ] ||
       [ "$DISK_SERIAL" != "" ];
    then
      echo -e -n " -"
      if [ "$DISK_CAPACITY" != "" ] &&
         [ $SHOW_CAPACITY -ne 0 ];
      then
        echo -e -n  " ${light_blue}$DISK_CAPACITY${colors_off}"
      fi
      # if [ "$DISK_FAMILY" != "" ]; then echo -e -n  " ${light_blue}$DISK_FAMILY${colors_off}"; fi
      if [ "$DISK_MODEL"  != "" ]; then echo -e -n  " ${light_blue}$DISK_MODEL${colors_off}"; fi
      if [ "$DISK_SERIAL" != "" ]; then echo -e -n  " ${light_blue}[$DISK_SERIAL]${colors_off}"; fi
    else
      echo -e -n " ${dark_grey}[keine weiteren Angaben]${colors_off}"
    fi
  fi
}

#===============================================================================
# Darstellung von Zahlen in einem für Menschen lesbaren Format
# Da Bash nur Integer-Werte verarbeiten kann und grundsätzlich abrundet,
# müssen wir uns mit einem Trick auch noch um die richtige Rundung kümmern ;)
# ----------------------------------------------------------------------------
# Parameter $1: Umzuwandelnde Zahl
# Parameter $2: Zielgröße -> B (Bytes) | K (KB) | M (MB) | G (GB)
# Parameter $3: Faktor für die Größe eines Kilobytes (ohne Angabe = 1024)
#===============================================================================
function show_human_bytes {
  THE_NUMBER=$1
  SIZE_FACTOR="$(echo -n $2 | tr '[:lower:]' '[:upper:]')"
  if [ "$3" != "" ];
  then
    BYTES_FACTOR=$3
  else
    BYTES_FACTOR=$((1024))
  fi
  ONE_KB=$((BYTES_FACTOR))
  HALF_KB=$((ONE_KB / 2))
  ONE_MB=$((ONE_KB * BYTES_FACTOR))
  HALF_MB=$((ONE_MB / 2))
  ONE_GB=$((ONE_MB * BYTES_FACTOR))
  HALF_GB=$((ONE_GB / 2))
  ONE_TB=$((ONE_GB * BYTES_FACTOR))
  HALF_TB=$((ONE_TB / 2))
  if [ $THE_NUMBER -ge $ONE_TB ] &&
     [ "$SIZE_FACTOR" != "G" ] &&
     [ "$SIZE_FACTOR" != "M" ] &&
     [ "$SIZE_FACTOR" != "K" ] &&
     [ "$SIZE_FACTOR" != "B" ];
  then
    ((THE_NUMBER+=HALF_TB))
    ((THE_NUMBER=THE_NUMBER/BYTES_FACTOR/BYTES_FACTOR/BYTES_FACTOR/BYTES_FACTOR))
    THE_NUMBER="${THE_NUMBER} TB"
  else
    if [ $THE_NUMBER -ge $ONE_GB ] &&
       [ "$SIZE_FACTOR" != "M" ] &&
       [ "$SIZE_FACTOR" != "K" ] &&
       [ "$SIZE_FACTOR" != "B" ];
    then
      ((THE_NUMBER+=HALF_GB))
      ((THE_NUMBER=THE_NUMBER/BYTES_FACTOR/BYTES_FACTOR/BYTES_FACTOR))
      THE_NUMBER="${THE_NUMBER} GB"
    else
      if [ $THE_NUMBER -ge $ONE_MB ] &&
         [ "$SIZE_FACTOR" != "K" ] &&
         [ "$SIZE_FACTOR" != "B" ];
      then
        ((THE_NUMBER+=HALF_MB))
        ((THE_NUMBER=THE_NUMBER/BYTES_FACTOR/BYTES_FACTOR))
        THE_NUMBER="${THE_NUMBER} MB"
      else
        if [ $THE_NUMBER -ge $ONE_KB ] &&
           [ "$SIZE_FACTOR" != "B" ];
        then
          ((THE_NUMBER+=HALF_KB))
          ((THE_NUMBER=THE_NUMBER/BYTES_FACTOR))
          THE_NUMBER="${THE_NUMBER} KB"
        else
          THE_NUMBER="${THE_NUMBER} B"
        fi
      fi
    fi
  fi
  echo "$THE_NUMBER"
}

#===============================================================================
# Anzeige der Kommandozeilen-Optionen
#===============================================================================
function show_options {
  echo -e " Optionen:\n"
  echo -e "  -a, --automode  Startet immer direkt den automatischen Medien-Auswahl-Modus.\n"
  echo -e "  -b, --bootonly  Kopiert NUR den Bootsektor (MBR) und keine sonstigen Daten"
  echo -e "                  (setzt die Optionen ocsmode und deepmode außer Kraft).\n"
  echo -e "  -d, --deepmode  Verwendet den Deep-Modus (dd) für den Kopier-Vorgang."
  echo -e "                  Dabei werden sämtliche Sektoren der Quelle kopiert, was"
  echo -e "                  zu einer sehr langen Dauer des Kopier-Vorgangs führen kann.\n"
  echo -e "  -h, --help      Zeigt diese Hilfe an.\n"
  echo -e "  -n, --noupdate  Sucht nicht nach Updates für dieses Skript.\n"
  echo -e "  -o, --ocsmode   Verwendet den OCS-Modus (Clonezilla) für den Kopier-Vorgang."
  echo -e "                  Dabei werden nur belegte Sektoren der Quelle kopiert, was"
  echo -e "                  den Kopiervorgang je nach Belegung erheblich beschleunigt"
  echo -e "                  (die Option ocsmode setzt die Option deepmode außer Kraft).\n"
  echo -e "  -s, --starter   Erstellt einen Desktop-Starter mit aktuellen Einstellungen.\n"
  echo -e "  -t, --noboots   Kopiert den Bootsektor (MBR) der Quelle NICHT und lässt den"
  echo -e "                  Bootsektor des Ziels unverändert. Diese Option steht nur in"
  echo -e "                  Verbindung mit dem OCS-Kopier-Modus (ocsmode) zur Verfügung.\n"
}

################################################################################
#                                                                              #
#                             Variablen definieren                             #
#                                                                              #
################################################################################
#===============================================================================
# URLs zum Download dieses Scriptes
#===============================================================================
THIS_SCRIPT_URL="https://migano.de/download/sd-copy/sd-copy"
THIS_SCRIPT_ICO="https://migano.de/download/sd-copy/png/sd-copy.png"

#===============================================================================
# Pfad-Angaben zu uns selbst (aufgerufenes Skript)
#===============================================================================
SCRIPT_PATH="$(pwd)"
SCRIPT_NAME="${0##*/}"

#===============================================================================
# Server-Verzeichnis, aus welchem zur Laufzeit dieses Skriptes weitere frei
# zugängliche (per URL direkt erreichbare) Ressourcen heruntergeladen werden.
#===============================================================================
RESSOURCE_SERVER_DIR="https://migano.de/download/sd-copy"

#===============================================================================
# Schriftfarben
#===============================================================================
# Text normal
black='\033[0;30m'
red='\033[0;31m'
green='\033[0;32m'
yellow='\033[0;33m'
blue='\033[0;34m'
purple='\033[0;35m'
cyan='\033[0;36m'
white='\033[0;97m'
# Text hell
dark_grey='\033[0;90m'
light_red='\033[0;91m'
light_green='\033[0;92m'
light_yellow='\033[0;93m'
light_blue='\033[0;94m'
light_purple='\033[0;95m'
light_cyan='\033[0;96m'
light_grey='\033[0;37m'
# Text fett
bold_black='\033[1;30m'
bold_red='\033[1;31m'
bold_green='\033[1;32m'
bold_yellow='\033[1;33m'
bold_blue='\033[1;34m'
bold_purple='\033[1;35m'
bold_cyan='\033[1;36m'
bold_white='\033[1;37m'
# Text unterstrichen
uline_black='\033[4;30m'
uline_red='\033[4;31m'
uline_green='\033[4;32m'
uline_yellow='\033[4;33m'
uline_blue='\033[4;34m'
uline_purple='\033[4;35m'
uline_cyan='\033[4;36m'
uline_white='\033[4;37m'
# Hintergrund
bg_black='\033[40m'
bg_red='\033[41m'
bg_green='\033[42m'
bg_yellow='\033[43m'
bg_blue='\033[44m'
bg_purple='\033[45m'
bg_cyan='\033[46m'
bg_white='\033[47m'
# Keine Farben
colors_off='\033[0m'
colors_invers='\033[7m'
# Linienfarbe
line_color='\033[0;90m'
#===============================================================================
# Textbausteine
#===============================================================================
# Trennzeilen
FULL_LINE="${line_color}$(printf '─%.0s' {1..80})${colors_off}"
HALF_LINE="${line_color}$(printf '─%.0s' {1..40})${colors_off}"
FULLSPACE=$(printf '\x20%.0s' {1..80})
# Kopfzeilen
HEADLINE_TEXT="${bold_white}${bg_blue}"
HEADLINE_TEXT+="$FULLSPACE"$'\n'
# HEADLINE_TEXT+="$(printf '\x20%.0s' {1..32})Simple Disk Copy$(printf '\x20%.0s' {1..32})"$'\n'
HEADLINE_TEXT+="$(printf '\x20%.0s' {1..27})SD-Copy | Simple Disk Copy$(printf '\x20%.0s' {1..27})"$'\n'
HEADLINE_TEXT+="${light_blue}${bg_blue}"
HEADLINE_TEXT+="$(printf '\x20%.0s' {1..37})v $VERSION$(printf '\x20%.0s' {1..37})"$'\n'
HEADLINE_TEXT+="$FULLSPACE"
HEADLINE_TEXT+="${colors_off}"
# Sonstige Texte
CANCEL_TEXT="Abbruch durch Benutzer."
# Text-Tags
ACHTUNG_TAG="${bold_yellow}Achtung${colors_off}"
ERROR_TAG="${bold_red}Fehler${colors_off}"
HINWEIS_TAG="${bold_blue}Hinweis${colors_off}"
OK_TAG="${bold_green}ok${colors_off}"

################################################################################
#                                                                              #
#                                Here we go ...                                #
#                                                                              #
################################################################################
#===============================================================================
# Eigenen Benutzernamen und Benutzer-ID ermitteln
#===============================================================================
if [ $SUDO_USER ]; then USER_USERNAME="$SUDO_USER"; else USER_USERNAME=$(whoami); fi
USER_UID=$(id -u $USER_USERNAME)

#===============================================================================
# Ordner zur Speicherung von Downloads festlegen
# ACHTUNG: Angaben OHNE Slash(/) am Ende!
#===============================================================================
if [ "$USER_USERNAME" == "root" ];
then
  USER_HOME_DIR="/root"
  DOWNLOAD_DIR="/tmp/$SCRIPT_NAME"
else
  USER_HOME_DIR="/home/$USER_USERNAME"
  DOWNLOAD_DIR="$USER_HOME_DIR/Downloads/$SCRIPT_NAME"
fi
DOWNLOAD_DIR+="_files"
if [ ! -d "$DOWNLOAD_DIR" ];
then
  mkdir -p "$DOWNLOAD_DIR" &>/dev/null
  if [ $? -eq 0 ];
  then
    chown -R "$USER_USERNAME:$USER_USERNAME" "$DOWNLOAD_DIR" &>/dev/null
    chmod -R 0755 "$DOWNLOAD_DIR" &>/dev/null
  fi
fi

#===============================================================================
# Desktop-Ordner des Benutzers (zur Erstellung des Programmsymbols / Icons)
# ACHTUNG: Angaben OHNE Slash (/) am Ende!
#===============================================================================
DESKTOP_DIR=""
if [ -d "/home/$USER_USERNAME/Schreibtisch" ] &&
   [ ! -L "/home/$USER_USERNAME/Schreibtisch" ];
then
  DESKTOP_DIR="/home/$USER_USERNAME/Schreibtisch"
else
  if [ -d "/home/$USER_USERNAME/Desktop" ] &&
     [ ! -L "/home/$USER_USERNAME/Desktop" ];
  then
    DESKTOP_DIR="/home/$USER_USERNAME/Desktop"
  fi
fi

#===============================================================================
# Kopfzeile ausgeben
#===============================================================================
printf %b '\e]10;#eeeeee\a' # Schriftfarbe (VT100) immer hell ;)
printf %b '\e]11;#242628\a' # Hintergrundfarbe (VT100) immer dunkel ;)
clear
echo -e "$HEADLINE_TEXT"

#===============================================================================
# Kommandozeilen-Parameter einlesen und entsprechende Optionen setzen
#===============================================================================
AUTOMATIC_MODE=0
BOOTSECTOR_ONLY=0
CHECK_UPDATE=1
CREATE_STARTER=0
NO_BOOTSECTOR=0
USE_DEEPMODE=0
USE_OCSMODE=0
for arg in $@;
do
  arg=$(printf %b "${arg}" | tr A-Z a-z)
  # ----------------------------------------------------------------------------
  # automode
  # ----------------------------------------------------------------------------
  if [ "$arg" == "--automode" ] || [ "$arg" == "-a" ];
  then
    AUTOMATIC_MODE=1
  fi
  # ----------------------------------------------------------------------------
  # bootonly
  # ----------------------------------------------------------------------------
  if [ "$arg" == "--bootonly" ] || [ "$arg" == "-b" ];
  then
    BOOTSECTOR_ONLY=1
  fi
  # ----------------------------------------------------------------------------
  # deep
  # ----------------------------------------------------------------------------
  if [ "$arg" == "--deepmode" ] || [ "$arg" == "-d" ];
  then
    USE_DEEPMODE=1
  fi
  # ----------------------------------------------------------------------------
  # help
  # ----------------------------------------------------------------------------
  if [ "$arg" == "--help" ] || [ "$arg" == "-h" ];
  then
    echo -e ""
    echo -e " Erstellt \"on-the-fly\" eine vollständige Kopie eines Speichermediums auf ein"
    echo -e " anderes Medium. Dazu müssen beide Speichermedien physisch angeschlossen sein."
    echo -e ""
    echo -e " Syntax: ${0} [Optionen]"
    echo -e ""
    show_options
    exit 0
  fi
  # ----------------------------------------------------------------------------
  # noupdate
  # ----------------------------------------------------------------------------
  if [ "$arg" == "--noupdate" ] || [ "$arg" == "-n" ];
  then
    CHECK_UPDATE=0
  fi
  # ----------------------------------------------------------------------------
  # ocsmode
  # ----------------------------------------------------------------------------
  if [ "$arg" == "--ocsmode" ] || [ "$arg" == "-o" ];
  then
    USE_OCSMODE=1
  fi
  # ----------------------------------------------------------------------------
  # starter
  # ----------------------------------------------------------------------------
  if [ "$arg" == "--starter" ] || [ "$arg" == "-s" ];
  then
    CREATE_STARTER=1
  fi
  # ----------------------------------------------------------------------------
  # noboots
  # ----------------------------------------------------------------------------
  if [ "$arg" == "--noboots" ] || [ "$arg" == "-t" ];
  then
    NO_BOOTSECTOR=1
  fi
done
# ------------------------------------------------------------------------------
# Konflikte bereinigen
# ------------------------------------------------------------------------------
if [[ $USE_DEEPMODE -eq 1 && $USE_OCSMODE -eq 1 ]];
then
  USE_DEEPMODE=0
  USE_OCSMODE=1
fi
if [ $BOOTSECTOR_ONLY -eq 1 ];
then
  USE_DEEPMODE=0
  USE_OCSMODE=0
fi
if [ $BOOTSECTOR_ONLY -eq 1 ] &&
   [ $NO_BOOTSECTOR -eq 1 ];
then
  echo -e ""
  echo -e " $ERROR_TAG: Optionen ${bold_white}bootonly${colors_off} und ${bold_white}noboots${colors_off} können nicht gemeinsam verwendet werden."
  echo -e ""
  show_options
  exit 1
fi

#===============================================================================
# Erforderliche Komponenten prüfen und ggf. nachinstallieren
#===============================================================================
echo -e ""
echo -e " Prüfe System-Voraussetzungen:"
required_packages=('clonezilla' 'eject' 'smartmontools' 'util-linux')
# -------------
# Schnell-Test
# -------------
ALL_COMPONENTS_INSTALLED=1
for required_pkg in ${required_packages[@]};
do
  ((ANZ_SPACES=12-${#required_pkg}))
  if [ $(LANG=en dpkg-query -W -f='${Status}' "$required_pkg" 2>/dev/null | grep -i -c -E "ok installed") -eq 0 ];
  then
    ALL_COMPONENTS_INSTALLED=0
    break
  fi
done
# ---------------------------------------------------
# Wenn alle benötigten Komponenten installiert sind,
# nur eine kurze Meldung anzeigen ...
# ---------------------------------------------------
required_errors=0
if [ $ALL_COMPONENTS_INSTALLED -eq 1 ];
then
  echo -e " Alle benötigten Komponenten sind installiert ... $OK_TAG"
# ------------------------------------------------------------------
# ... sonst alle Komponenten anzeigen und fehlende installieren ...
# ------------------------------------------------------------------
else
  for required_pkg in ${required_packages[@]};
  do
    echo -e -n " Modul ${bold_cyan}$required_pkg${colors_off}"
    ((ANZ_SPACES=13-${#required_pkg}))
    insert_spaces $ANZ_SPACES
    echo -e -n " ... "
    if [ $(LANG=en dpkg-query -W -f='${Status}' "$required_pkg" 2>/dev/null | grep -i -c -E "ok installed") -eq 0 ];
    then
      echo -e -n "wird installiert ... "
      apt install "$required_pkg" -y &>/dev/null
      if [ $? -eq 0 ];
      then
        echo -e "$OK_TAG"
      else
        ((required_errors+=1))
        echo -e "$ERROR_TAG"
      fi
    else
      echo -e "$OK_TAG"
    fi
  done
fi

#===============================================================================
# Wichtige Hinweise anzeigen und Skript bei fehlenden Komponenten ggf. beenden
#===============================================================================
if ! lsblk --version &>/dev/null;
then
  echo -e ""
  echo -e " $ACHTUNG_TAG: Leider stehen auf diesem System nicht alle benötigten Komponenten"
  echo -e " zur Verfügung (util-linux). Das Skript wird daher jetzt beendet."
  echo -e ""
  exit 1
fi
boot_device="$(findmnt -n / 2>/dev/null | awk '{ print $2 }' | sed -E "s/\/dev\///" | sed -E "s/(sd[a-z])[0-9]+/\1/" | sed -E "s/(^mm[a-z]*[0-9]+)(.)*/\1/")"
echo -e ""
echo -e -n " System gebootet von ... ${bold_purple}$boot_device${colors_off}${light_blue}"
show_disk_info "$boot_device" 0 21 0
echo -e "${colors_off}"
if [ $required_errors -gt 0 ];
then
  echo -e ""
  echo -e " $HINWEIS_TAG: Auf diesem System fehlen einige wichtige Komponenten, daher"
  echo -e " stehen nicht alle Funktionen des Skripts zur Verfügung."
fi

#===============================================================================
# Auf neuere Version prüfen
#===============================================================================
if [ $CHECK_UPDATE -eq 1 ];
then
  LOCAL_DOWNLOAD_FILE="./$SCRIPT_NAME.new"
  wget -nv -O "$LOCAL_DOWNLOAD_FILE" "$THIS_SCRIPT_URL" &>/dev/null
  if [ $? -eq 0 ] &&
     [ -s "$LOCAL_DOWNLOAD_FILE" ] &&
     [ $(grep -i -c -E "Error\s*404" "$LOCAL_DOWNLOAD_FILE") -eq 0 ];
  then
    chown -R "$USER_USERNAME:$USER_USERNAME" "$LOCAL_DOWNLOAD_FILE" &>/dev/null
    chmod -R 0755 "$LOCAL_DOWNLOAD_FILE" &>/dev/null
    NEW_VERSION=$(grep -i -E "^\s*version=" "$LOCAL_DOWNLOAD_FILE" | sed -E "s/^\s*version=//i" | sed -E "s/\"//g" | xargs 2>/dev/null)
    OLD_VERSION_VALUE=$(get_version_value ${VERSION})
    NEW_VERSION_VALUE=$(get_version_value ${NEW_VERSION})
    if [ $OLD_VERSION_VALUE -lt $NEW_VERSION_VALUE ];
    then
      echo -e ""
      echo -e " Version ${light_yellow}$NEW_VERSION${colors_off} ist verfügbar. Es wird empfohlen, die neue Version zu verwenden."
      ask_yes_or_no "Alte Version sichern und neue Version verwenden" "j"
      if [ $? -eq 1 ];
      then
        mv -f "${0}" "${0}.bak" &>/dev/null
        if [ $? -eq 0 ];
        then
          echo -e " Alte Version gesichert als ${bold_purple}${0}.bak${colors_off}"
          mv -f "$LOCAL_DOWNLOAD_FILE" "${0}"
          if [ $? -eq 0 ];
          then
            echo -e " ${bold_white}$SCRIPT_NAME${colors_off} wurde aktualisiert und beendet - bitte jetzt neu aufrufen ... $OK_TAG"
          else
            echo -e " $ERROR_TAG: Die Aktualisierung konnte leider ${bold_red}nicht${colors_off} korrekt durchgeführt werden."
            echo -e " Zum Überspringen der Aktualisierung bitte die Option ${light_cyan}--noupdate${colors_off} verwenden."
          fi
          exit 1
        else
          echo -e " $ERROR_TAG: Sicherung konnte nicht angelegt werden"
        fi
      else
        remove_file "$LOCAL_DOWNLOAD_FILE"
      fi
      echo -e "$FULL_LINE"
    else
      remove_file "$LOCAL_DOWNLOAD_FILE"
    fi
  else
    remove_file "$LOCAL_DOWNLOAD_FILE"
  fi
fi

#===============================================================================
# Erstellung eines Starters
#===============================================================================
# --------------------------------------------------------------------
# Explizit mit Verwendung der aktuellen Parameter
# --------------------------------------------------------------------
if [ $CREATE_STARTER -eq 1 ];
then
  create_starter 1
else
  # ------------------------------------------------------------------
  # Wenn noch kein Starter existiert, dann nur einen Standard-Starter
  # ------------------------------------------------------------------
  if [ $(find "$DESKTOP_DIR" -type f -iname "sd-copy*.desktop" 2>/dev/null | wc -l) -eq 0 ];
  then
    echo -e ""
    echo -e " $HINWEIS_TAG: Es scheint kein ${light_cyan}Starter${colors_off} für SD-Copy v$VERSION angelegt zu sein."
    ask_yes_or_no "Jetzt Starter (Symbol) auf dem Desktop anlegen" "j"
    if [ $? -eq 1 ];
    then
      create_starter 0
    fi
  fi
fi

#===============================================================================
# Liste aller Disk-Devices erstellen
#===============================================================================
declare -A device_list
first_new_char=""
get_disk_letter 0
devices_in_list=${#device_list[@]}
echo -e ""

#===============================================================================
# Auswahl von Quelle und Ziel
#===============================================================================
# ------------------------------------------------------------------------------
# Manuelle Auswahl (wenn mindestens 2 Disks angeschlossen sind)
# ------------------------------------------------------------------------------
if [ $AUTOMATIC_MODE -eq 0 ] &&
   [ $devices_in_list -gt 1 ];
then
  do_auto_select=0
  # ----------------------------------------------------------------------------
  # Auswahlliste anzeigen
  # ----------------------------------------------------------------------------
  echo -e " Folgende verwendbare Speichermedien sind gerade angeschlossen:"
  x=0
  while [ $x -lt $devices_in_list ];
  do
    echo -e -n " [${bold_yellow}${device_list[$x]}${colors_off}] ${bold_white}sd${device_list[$x]}${colors_off}"
    show_disk_info "sd${device_list[$x]}" 1 20 0
    echo -e ""
    ((x+=1))
  done
  echo -e ""
  echo -e " Zur Auswahl die entsprechende Taste drücken, oder zum Start des automatischen"
  echo -e " Modus mit selektivem Medien-Anschluss leere Eingabe machen (Enter drücken)."

  # ----------------------------------------------------------------------------
  # Quelle auswählen
  # ----------------------------------------------------------------------------
  echo -e ""
  echo -e -n " Bitte ${bold_yellow}Quelle${colors_off} auswählen: "
  source_device=""
  source_select=0
  while [ $source_select -eq 0 ] &&
        [ $do_auto_select -eq 0 ];
  do
    read -N 1 -r -s source_device
    source_device=$(echo "$source_device" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z]*//g')
    if [ "$source_device" != "" ];
    then
      source_device="sd$source_device"
      x=0
      while [ $x -lt $devices_in_list ];
      do
        if [ "$source_device" == "sd${device_list[$x]}" ];
        then
          source_select=1
        fi
        ((x+=1))
      done
    else
      echo -e "keine Auswahl - automatischer Modus wird gestartet."
      echo -e "$FULL_LINE"
      do_auto_select=1
    fi
  done

  # ----------------------------------------------------------------------------
  # Wenn eine Quelle ausgewählt wurde, dann auch ein Ziel auswählen
  # ----------------------------------------------------------------------------
  if [ $do_auto_select -eq 0 ];
  then
    echo -e -n "${bold_yellow}$source_device${colors_off}"
    show_disk_info "$source_device" 1 14 0
    echo -e ""
    echo -e -n " Bitte ${bold_yellow}Ziel${colors_off} auswählen:   "
    dest_device=""
    dest_select=0
    while [ $dest_select -eq 0 ] &&
          [ $do_auto_select -eq 0 ];
    do
      read -N 1 -r -s dest_device
      dest_device=$(echo "$dest_device" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z]*//g')
      if [ "$dest_device" != "" ];
      then
        dest_device="sd$dest_device"
        x=0
        while [ $x -lt $devices_in_list ];
        do
          if [ "$dest_device" == "sd${device_list[$x]}" ] &&
             [ "$dest_device" != "$source_device" ];
          then
            dest_select=1
          fi
          ((x+=1))
        done
      else
        echo -e "keine Auswahl - automatischer Modus wird gestartet."
        echo -e "$FULL_LINE"
        do_auto_select=1
      fi
    done
    if [ $do_auto_select -eq 0 ];
    then
      echo -e -n "${bold_yellow}$dest_device${colors_off}"
      show_disk_info "$dest_device" 1 14 0
      echo -e ""
    fi
  fi
else
  if [ $AUTOMATIC_MODE -eq 0 ] &&
     [ $devices_in_list -lt 2 ];
  then
    echo -e " $HINWEIS_TAG: Es wurden nicht genug angeschlossene Speichermedien zum Kopieren"
    echo -e " gefunden, daher wird jetzt der automatische Modus gestartet."
    echo -e ""
    echo -e "$FULL_LINE"
  fi
  do_auto_select=1
fi

# ------------------------------------------------------------------------------
# Automatischer Modus (wenn weniger als 2 Disks angeschlossen sind,
# oder die manuelle Auswahl abgebrochen wurde)
# ------------------------------------------------------------------------------
if [ $do_auto_select -eq 1 ];
then
  echo -e " ${bold_white}Automatischer Modus${colors_off}"
  echo -e "$HALF_LINE"
  echo -e " $ACHTUNG_TAG: Bitte entferne zunächst vollständig das Quell- UND Ziel-Medium,"
  echo -e -n " sofern diese bereits angeschlossen sind, und drücke dann auf Enter ... "
  read -N 1 -r -s dummy
  echo -e "$OK_TAG"
  device_list=()
  get_disk_letter 0
  echo -e ""
  echo -e " Die jeweiligen Medien werden nun bei Anschluss automatisch erkannt."
  echo -e ""
  echo -e -n " Bitte ${bold_yellow}Quelle${colors_off} anschließen ... "
  new_disc_letter=""
  while [ "$new_disc_letter" == "" ];
  do
    get_disk_letter 1
    new_disc_letter="$first_new_char"
    (sleep 1 &>/dev/null)
  done
  source_device="sd${new_disc_letter}"
  echo -e -n "${bold_yellow}$source_device${colors_off}"
  show_disk_info "$source_device" 1 12 0
  echo -e ""
  echo -e -n " Bitte ${bold_yellow}Ziel${colors_off} anschließen ...   "
  new_disc_letter=""
  while [ "$new_disc_letter" == "" ];
  do
    get_disk_letter 1
    new_disc_letter="$first_new_char"
    (sleep 1 &>/dev/null)
  done
  dest_device="sd${new_disc_letter}"
  echo -e -n "${bold_yellow}$dest_device${colors_off}"
  show_disk_info "$dest_device" 1 12 0
  echo -e ""
fi

#===============================================================================
# Durchführung des Kopier-Vorgangs
#===============================================================================
# ------------------------------------------------------------------------------
# Nur den Boot-Sektor immer mit dd
# ------------------------------------------------------------------------------
if [ $BOOTSECTOR_ONLY -eq 0 ];
then
  # --------------------------------------------------
  # Wenn Clonezilla nicht ordentlich installiert ist,
  # dann nur den Deep-Modus (dd) zulassen.
  # --------------------------------------------------
  if [ ! -f "/usr/sbin/ocs-onthefly" ];
  then
    # ---------------------------------------------------------------------
    # Wenn ocs-Modus explizit gewünscht, dann Hinweis, dass das nicht geht
    # ---------------------------------------------------------------------
    if [ $USE_OCSMODE -eq 1 ];
    then
      echo -e " $HINWEIS_TAG: Es steht nur der Deep-Mode (Klonen mit dd) zur Verfügung,"
      echo -e " der Kopier-Vorgang wird daher sehr viel Zeit in Anspruch nehmen!"
    fi
    deep_mode=1
  else
    # --------------------------------------------------------------------
    # Wenn kein Modus gesetzt ist, dann gewünschten Kopier-Modus abfragen
    # --------------------------------------------------------------------
    if [ $USE_DEEPMODE -eq 0 ] &&
       [ $USE_OCSMODE -eq 0 ];
    then
      echo -e ""
      echo -e " ${bold_white}OK${colors_off}, ich bin bereit für den Kopier-Vorgang."
      echo -e ""
      echo -e " $HINWEIS_TAG: Im Standard werden nur die Sektoren kopiert, welche auch mit Daten"
      echo -e " belegt sind, wodurch der Kopier-Vorgang ganz erheblich beschleunigt werden"
      echo -e " kann. Um zudem auch alle unbelegten Sektoren zu kopieren, kann statt dessen"
      echo -e " der Deep-Mode (Klonen mit dd) verwendet werden, was je nach Belegung der"
      echo -e " Quelle allerdings sehr viel länger (bis zu einigen Stunden) dauern kann!"
      echo -e ""
      ask_yes_or_no "Soll der Deep-Mode verwendet werden?" "n"
      deep_mode=$?
      echo -e -n " ${bold_white}OK${colors_off}, also "
      if [ $deep_mode -eq 1 ];
      then
        echo -e "im Deep-Mode kopieren - das kann einige Stunden dauern!"
      else
        echo -e "${bold_blue}keinen${colors_off} Deep-Mode verwenden - das geht schneller."
      fi
    else
      # ---------------------------------------------------
      # Wenn ein Kopiermodus-gesetzt ist, diesen verwenden
      # ---------------------------------------------------
      if [ $USE_DEEPMODE -eq 1 ];
      then
        deep_mode=1
      else
        deep_mode=0
      fi
    fi
  fi
else
  deep_mode=1
fi
echo -e ""

# ------------------------------------------------------------------------------
# Sicherheitsabfragen
# ------------------------------------------------------------------------------
echo -e " Sorry, die obligatorische Sicherheits-Frage muss ich natürlich noch stellen:"
echo -e -n " Das Ziel ist ${bold_white}$dest_device${colors_off}"
show_disk_info "$dest_device" 1 20 0
echo -e ""
ask_yes_or_no "Soll ${bold_yellow}$source_device${colors_off} auf ${bold_yellow}$dest_device${colors_off} kopiert werden?" ""
if [ $? -eq 1 ];
then
  echo -e ""
  echo -e " Zur Sicherheit noch ein letztes Mal - versprochen, danach geht's sofort los!"
  echo -e " $ACHTUNG_TAG: ALLE Daten auf ${bold_white}$dest_device${colors_off} werden UNWIEDERBRINGLICH überschrieben!"
  ask_yes_or_no "Jetzt wirklich ${bold_yellow}$source_device${colors_off} auf ${bold_yellow}$dest_device${colors_off} kopieren?" ""
  if [ $? -eq 1 ];
  then
    # --------------------------------------------------------------------------
    # Vorher eventuell ausgeworfene Geräte wieder neu verbinden
    # --------------------------------------------------------------------------
    if [ "/dev/${source_device}" != "/dev/$boot_device" ] &&
       [ $(ls -la /dev/${source_device}* 2>/dev/null | wc -l ) -eq 1 ];
    then
      eject -t /dev/${source_device} &>/dev/null
    fi
    if [ "/dev/${dest_device}" != "/dev/$boot_device" ] &&
       [ $(ls -la /dev/${dest_device}* 2>/dev/null | wc -l ) -eq 1 ];
    then
      eject -t /dev/${dest_device} &>/dev/null
    fi

    # --------------------------------------------------------------------------
    # Eingehängte Partitionen aushängen (mehrfach versuchen)
    # --------------------------------------------------------------------------
    echo -e ""
    echo -e " Hänge alle betroffenen Partitionen aus:"
    UMOUNTS_RESULT=0
    # ---------------------------------------------
    # Alle Partitionen des Quell-Mediums aushängen
    # ---------------------------------------------
    p=1
    while [ $p -lt 100 ] &&
          [ $UMOUNTS_RESULT -eq 0 ];
    do
      if [ $(df | grep -i -c -E "\/dev\/${source_device}${p}") -ne 0 ] ||
         [ $(mount | grep -i -c -E "\/dev\/${source_device}${p}") -ne 0 ];
      then
        echo -e -n " - /dev/${source_device}${p} ... "
        umount "/dev/${source_device}${p}" &>/dev/null
        UMOUNTS_RESULT=$?
        if [ $UMOUNTS_RESULT -eq 0 ];
        then
          echo -e "$OK_TAG"
        else
          echo -e "$ERROR_TAG"
        fi
      fi
      ((p+=1))
    done
    # --------------------------------------------
    # Alle Partitionen des Ziel-Mediums aushängen
    # --------------------------------------------
    p=1
    while [ $p -lt 100 ] &&
          [ $UMOUNTS_RESULT -eq 0 ];
    do
      if [ $(df | grep -i -c -E "\/dev\/${dest_device}${p}") -ne 0 ] ||
         [ $(mount | grep -i -c -E "\/dev\/${dest_device}${p}") -ne 0 ];
      then
        echo -e -n " - /dev/${dest_device}${p} ... "
        umount "/dev/${dest_device}${p}" &>/dev/null
        UMOUNTS_RESULT=$?
        if [ $UMOUNTS_RESULT -eq 0 ];
        then
          echo -e "$OK_TAG"
        else
          echo -e "$ERROR_TAG"
        fi
      fi
      ((p+=1))
    done

    if [ $UMOUNTS_RESULT -ne 0 ];
    then
      echo -e " Es konnten nicht alle Partitionen freigegeben werden!"
      echo -e " Das Skript kann daher leider nicht fortgeführt werden."
      exit 1
    fi

    # --------------------------------------------------------------------------
    # Kopieren
    # --------------------------------------------------------------------------
    echo -e ""
    echo -e " Starte Kopier-Vorgang von ${bold_yellow}$source_device${colors_off} nach ${bold_yellow}$dest_device${colors_off} ..."
    echo -e "$FULL_LINE"
    COPY_RESULT=0

    # ----------------------------------------------------------
    # Alle Partitionen mit "ocs-onthefly" (Clonezilla) kopieren
    # ----------------------------------------------------------
    if [ $deep_mode -eq 0 ] &&
       [ $BOOTSECTOR_ONLY -eq 0 ];
    then
      NOBOOTOPT=""
      if [ $NO_BOOTSECTOR -eq 1 ]; then NOBOOTOPT="-t"; fi
      /usr/sbin/ocs-onthefly -batch -e1 auto -e2 -icds -iui -ius -j2 -nogui -pa true -rescue -rvd ${NOBOOTOPT} --source ${source_device} --target ${dest_device}
      COPY_RESULT=$?
    fi

    # -----------------------------------------------------------------
    # Gesamtes Medium mit "dd" klonen und dabei Lese-Fehler ignorieren
    # -----------------------------------------------------------------
    if [ $deep_mode -eq 1 ] &&
       [ $BOOTSECTOR_ONLY -eq 0 ];
    then
      dd conv=noerror,sync if=/dev/${source_device} of=/dev/${dest_device} status=progress
      COPY_RESULT=$?
    fi

    # --------------------------
    # Bootsektor (MBR) kopieren
    # --------------------------
    if [ $COPY_RESULT -eq 0 ] &&
       [ $NO_BOOTSECTOR -eq 0 ];
    then
      if [ $BOOTSECTOR_ONLY -eq 0 ]; then echo -e "$FULL_LINE"; fi
      echo -e -n " Kopiere Bootsektor (MBR) ... "
      dd conv=noerror,sync if=/dev/${source_device} of=/dev/${dest_device} bs=512 count=2 &>/dev/null
      COPY_RESULT=$?
      if [ $COPY_RESULT -eq 0 ];
      then
        echo -e "$OK_TAG"
      else
        echo -e "$ERROR_TAG"
      fi
    fi

    # --------------------------------------------------------------------------
    # Ende des Kopier-Vorgangs
    # --------------------------------------------------------------------------
    echo -e "$FULL_LINE"
    if [ $COPY_RESULT -eq 0 ];
    then
      echo -e " Fertig, alles erledigt ... $OK_TAG"
    else
      echo -e " $ERROR_TAG, der Kopier-Vorgang war nicht erfolgreich!"
    fi
  else
    echo -e " $CANCEL_TEXT"
  fi
else
  echo -e " $CANCEL_TEXT"
fi

#===============================================================================
# Ende des Skripts
#===============================================================================
# ------------------------------------------------------------------------------
# Download-Ordner ganz löschen wenn keine Dateien mehr darin sind
# ------------------------------------------------------------------------------
if [ "$DOWNLOAD_DIR" != "" ] &&
   [ "$DOWNLOAD_DIR" != "/" ] &&
   [ "$DOWNLOAD_DIR" != "/tmp" ] &&
   [ -d "$DOWNLOAD_DIR" ] &&
   [ $(ls -A "$DOWNLOAD_DIR" | wc -w) -eq 0 ];
then
  rmdir "$DOWNLOAD_DIR" &>/dev/null
fi
# ------------------------------------------------------------------------------
# Auf Wiedersehen
# ------------------------------------------------------------------------------
echo -e ""
echo -e " ${bold_green}Vielen Dank${colors_off} für die Nutzung und auf Wiedersehen :)"
