#!/bin/bash
# flash-knoppix - install KNOPPIX on flash disk or CD/DVD
# (C) Klaus Knopper 2008-202020
# License: GPL V2
#
# Changes for Knoppix 7.0:
# - Replacing Xdialog (GTK1) by accessible zenity
# - Skip copy of persistent home when installing from flash to flash

# Changes for Knoppix 9.0:
# - Option for creating a minimal version
# - Option for burning a CD/DVD

PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin"
export PATH

[ -r /etc/default/locale ] && . /etc/default/locale
[ -r /etc/sysconfig/i18n ] && . /etc/sysconfig/i18n

case "$LANG" in
 de*)
  MSG_INTRO="flash-knoppix: Mit diesem Programm wird eine bootfähige Kopie von\nKNOPPIX auf einem USB-Datenspeicher oder einer Festplatte und\noptional ein Overlay zur Speicherung persönlicher Daten auf dem\nZielmedium erzeugt, als Container-Datei oder separate Partition,\nmit oder ohne Verschlüsselung.\n\nBitte wählen Sie die Optionen aus:" 
  MSG_ALLOWHD="Installation auch auf internen Festplatten erlauben"
  MSG_NOALLOWHD="Installation nur auf (Flash-)Wechselmedien erlauben"
  MSG_BURN="Eine CD/DVD brennen"
  MSG_BURNING="Brenne Image auf CD/DVD, bitte warten..."
  MSG_START_BURN="Hinweis: Bitte während des Brennens das laufende System nicht benutzen,\num den Brennvorgang nicht zu beeinträchtigen.\n\nBrennvorgang jetzt starten?"
  MSG_MINIMAL="Eine minimale Version erstellen (CD-Größe, 700MB)"
  MSG_MINIMAL_DESC="flash-knoppix kann eine minimale Version von KNOPPIX erstellen,\nindem die größeren Overlay-Images nicht mitkopiert werden.\nDie kleine Version enthält nur ein sehr schmales Linux Basis-System,\nSoftware zur Datenrettung und einen Browser.\n\nSoll eine Mini-Version von Knoppix erstellt werden (ohne LibreOffice etc.)?"
  MSG_TARGET="flash-knoppix: KNOPPIX komprimiert auf Flash Disk installieren.\n\nBitte das gewünschte Ziel angeben:"
  INFO_TARGET="Ziel:"
  MSG_READY="Fertig.
Sie können den Datenträger jetzt entfernen."
  MSG_MOUNTED="ist noch gemountet."
  MSG_CHECKING="Untersuche"
  MSG_SELECT="Bitte das Verzeichnis angeben, in dem sich die KNOPPIX-Daten befinden."
  MSG_BOOTREC="Bootrecord einrichten auf" 
  MSG_NOTFOUND="Keine Bootkonfiguration gefunden (weder boot/isolinux/isolinux.cfg noch boot/syslinux/syslinux.cfg), der Bootlader wird vermutlich nicht funktionieren."
  MSG_WRITING="Schreibe Daten..."
  MSG_SIZE_OVERLAY="KNOPPIX kann eine \"Overlay\"-Datei verwenden, um Daten permanent zu speichern.\nWenn gewünscht, bitte Größe angeben (mindestens 200MB, frei: %sMB)."
  MSG_SIZE_OVERLAY_ADVANCED="Bitte die Größe der Overlay-Partition angeben, auf der Ihre\nDaten permanent gespeichert werden.\n(mindestens 400MB, frei: %sMB)."
  MSG_CRYPT_OVERLAY="Sollen Ihre eigenen Daten mit AES256 (=Advanced Encryption Standard 256bit, s.a.\nhttp://csrc.nist.gov/encryption/aes/) verschlüsselt werden?\n\nHierzu ist die Eingabe eines Passwortes beim Einrichten sowie beim\nSystemstart erforderlich.\n\nOhne Kenntnis des korrekten Passwortes ist der Zugriff auf die Daten\nnicht möglich, dadurch sind die möglicherweise sensiblen Daten einerseits bei\nVerlust des Datenträgers vor unbefugtem Zugriff geschützt, andererseits sind\nsie bei vergessenem Passwort auch nicht mehr vefügbar."
  MSG_PASSWORD="AES256 Verschlüsselungs Passwort (mindestens 8 Zeichen):"
  MSG_PASSWORD2="Bitte Passwort zur Sicherheit noch einmal eingeben:"
  MSG_PASSWORDS_NOMATCH="Die beiden Passwörter stimmen nicht überein oder sind zu kurz.\nBitte noch einmal versuchen."
  MSG_OVERLAY="Erzeuge Overlay [%s MB]..."
  MSG_QUESTION_PARTITION="Datenträger partitionieren und formatieren?\nWARNUNG: Alle Daten werden dabei gelöscht!\nNein = nur KNOPPIX-Daten auf ggf. vorhandene Partition kopieren"
  MSG_QUESTION_PARTITION_ADVANCED="Datenträger neu partitionieren und formatieren?
WARNUNG: Alle Daten werden dabei gelöscht!\nNein = Abbrechen"
  MSG_QUESTION_REALLY_FORMAT="Möchten Sie dies wirklich tun?
WARNUNG: Alle Daten auf dem Datenträger werden dabei gelöscht!"
  MSG_FORMAT="Formatiere"
  MSG_PARTITION="Partitioniere"
  MSG_ERROR_NODISK="Keine Flashdisk(s) gefunden."
  MSG_ERROR_NOCD="Kein CD/DVD-Brenner gefunden."
  MSG_ERROR_INCOMPATIBLE="Das Flash-Medium ist nicht richtig partitioniert.\nDie erste (primäre) Partition muss DOS/FAT32 sein."
  MSG_FAT_EXISTS="Ein FAT32-Dateisystem existiert auf"
  MSG_KNOPPIX_EXISTS="Ein installiertes KNOPPIX-System existiert auf"
  MSG_OVERLAY_IMAGE_EXISTS="Ein Overlay-Image ist vorhanden."
  MSG_ENCRYPTED_OVERLAY_IMAGE_EXISTS="Ein verschlüsseltes Overlay-Image ist vorhanden."
  MSG_OVERLAY_PARTITION_EXISTS="Eine Overlay-Partition ist vorhanden."
  MSG_UPDATE_SELECT="Möchten Sie die bestehende KNOPPIX-Installation aktualisieren?"
  MSG_UPDATE_CLEAN="NUR persönliche Daten und Einstellungen (\$HOME) behalten. (empfohlen)"
  MSG_UPDATE_KEEP="ALLE, auch inkompatible Modifikationen behalten (nicht empfohlen)"
  MSG_UPDATE_DELETE="Alles löschen / Neu (alle alten Daten gehen verloren!)"
  MSG_METHOD_SELECT="Bitte wählen Sie die Installationsmethode:"
  METHOD_NEW_IMAGE="Installation auf FAT32 mit (optionaler) Overlay-Datei <4GB."
  METHOD_NEW_PARTITION="Installation auf FAT32 mit zusätzlicher Overlay-Partition. (empfohlen)"
  METHOD_NOTHING="Kein Overlay (read-only wie CD/DVD)."
  MSG_SIZE_OVERLAY_PARTITION="Bitte geben Sie die gewünschte Größe der Overlay-Partition ein (MB)."
  MSG_ERROR_TOOSMALL="Die Overlay-Größe ist zu klein!\n(mindestens 400MB erforderlich)"
  MSG_ERROR_BOOT_TOOSMALL="Die Größe der Bootpartition ist zu klein für das Update!"
  MSG_ERROR_CANNOT_MOUNT_OVERLAY="Kann das Overlay auf dem Zieldatenträger nicht einbinden!\nFalsches Passwort?"
  MSG_ADD_CUSTOM="Möchten Sie Knoppix remastern?\n\nAlle Änderungen seit Erstellung des Originals werden dann als neues,\nkomprimiertes Image in der erzeugten Kopie hinzufügt.\nWarnung: Dies beinhaltet auch die aktuellen Netzwerk-Einstellungen,\npersönliche Daten, Bookmarks, Passwörter des laufenden Systems.\n\nDas Komprimieren dauert u.U. sehr lange und benötigt etwa %d MB RAM.\nFür das zusätzliche Dateisystem-Image werden außerdem zusätzliche %d MB\nauf der ersten Partition reserviert. (Sie können die Größe\ndieser Partition auch höher einstellen)."
  MSG_ADD_CUSTOM_WAIT="%d MB geänderte Daten werden gesammelt und komprimiert,\ndies kann sehr lange dauern.\n\nBitte verändern Sie in dieser Zeit nichts am System\n(am besten gar nichts tun, bis dieses Fenster\nverschwindet)."
  ERROR_ADD_CUSTOM="Fehler beim Remastern"
  MSG_ADD_CUSTOM_ERROR="Etwas ist schiefgegangen (vielleicht Datenträger voll?).\nBitte prüfen Sie das Protokoll:"
  ;;
 *)
  MSG_INTRO="flash-knoppix: This program creates a bootable copy of KNOPPIX\non an USB flash disk or hard disk, optionally with an overlay\nfor storing personal data in form of a container or separate\npartition on the target media, with or without encryption.\n\nPlease select options:" 
  MSG_ALLOWHD="Installation also on fixed hard disks"
  MSG_NOALLOWHD="Installation only on removable (flash-)devices"
  MSG_BURN="Burn a CD/DVD"
  MSG_BURNING="Burning image to CD/DVD, please wait..."
  MSG_MINIMAL="Create a minimal version (CD-size, 700MB)"
  MSG_MINIMAL_DESC="$0 can create a minimal version of KNOPPIX\nby skipping the larger overlay images during copy.\nThe small version contains only a small Linux base system,\nsoftware for data rescue and a browser.\n\nDo you want to create a minimal version of KNOPPIX (no LibreOffice etc.)?"
  MSG_START_BURN="Caution: Please don't use the system during the burn process\nin order to not interrupting data flow.\n\nStart burning CD/DVD now?"
  MSG_TARGET="flash-knoppix: Install KNOPPIX compressed to flash disk.\n\nPlease select desired target device:"
  INFO_TARGET="Target:"
  MSG_READY="Finished.
You can now remove device from drive."
  MSG_MOUNTED="is already mounted."
  MSG_CHECKING="Checking"
  MSG_SELECT="Please enter directory containing KNOPPIX files."
  MSG_BOOTREC="Creating boot record on"
  MSG_NOTFOUND="No boot configuration found (no boot/isolinux/isolinux.cfg), bootloader will probably not work."
  MSG_WRITING="Writing data..."
  MSG_SIZE_OVERLAY="KNOPPIX can use an \"Overlay\"-file for storing data permanently.\nIf you want this, please enter desired size (minimum 200MB, free: %sMB)."
  MSG_SIZE_OVERLAY_ADVANCED="Please enter the size of the Overlay partition\nfor storing your data permanently.\n(minimum 400MB, free: %sMB)."
  MSG_CRYPT_OVERLAY="Would you like to encrypt the overlay using AES256 (=Advanced Encryption\nStandard 256bit, http://csrc.nist.gov/encryption/aes/)?\n\nFor this type of encryption, entering a password for creation as well as\nat system start is necessary.\n\nWithout knowing this password, reading saved data is not possible.\nBecause of that, encrypted data is still safe against unauthorized\naccess in case the storage device containig the data gets lost or stolen.\nOn the other hand, all saved data is inaccessible if you forget the password,\nand there is no way to recover."
  MSG_PASSWORD="AES256 Encryption Key (minimum 8 chars):"
  MSG_PASSWORD2="Please enter the same password again, just to be sure:"
  MSG_PASSWORDS_NOMATCH="Passwords are not identical, or just too short.\nPlease try again."
  MSG_OVERLAY="Creating overlay [%s MB]..."
  MSG_QUESTION_PARTITION="Partition and format device?\nCAUTION: All data will be erased!\nNo = only copy KNOPPIX data to existing partition"
  MSG_QUESTION_PARTITION_ADVANCED="Repartition and format device?\nCAUTION: All data will be erased!\nNo = Exit program"
  MSG_QUESTION_REALLY_FORMAT="Do you really want to do this?\nWARNING: ALL DATA ON WILL BE ERASED!"
  MSG_FORMAT="Formatting"
  MSG_PARTITION="Partitioning"
  MSG_ERROR_NODISK="No flash disk(s) found."
  MSG_ERROR_NOCD="No CD/DVD burner found on your computer."
  MSG_ERROR_INCOMPATIBLE="Flashdisk is not partitioned properly.\nThe first (primary) partition must be DOS/FAT32."
  MSG_FAT_EXISTS="A FAT32 file system exists on"
  MSG_KNOPPIX_EXISTS="An installed KNOPPIX system exists on"
  MSG_OVERLAY_IMAGE_EXISTS="An Overlay image is present."
  MSG_ENCRYPTED_OVERLAY_IMAGE_EXISTS="An encrypted Overlay image is present."
  MSG_OVERLAY_PARTITION_EXISTS="An overlay partition is present."
  MSG_METHOD_SELECT="Please select installation method:"
  MSG_UPDATE_SELECT="Do you want to update the currently installed KNOPPIX installation?"
  MSG_UPDATE_CLEAN="Keep ONLY personal data and settings (\$HOME) (recommended)"
  MSG_UPDATE_KEEP="Keep ALL modifications, even if incompatible (not recommended)"
  MSG_UPDATE_DELETE="Delete everything / New (all old data will be lost!)"
  METHOD_NEW_IMAGE="Installation on FAT32 with (optional) overlay file <4GB."
  METHOD_NEW_PARTITION="Installation on FAT32 with additional overlay partition."
  METHOD_NOTHING="No Overlay (read-only like CD/DVD)."
  MSG_SIZE_OVERLAY_PARTITION="Please enter desired size of overlay partition (MB)."
  MSG_ERROR_BOOT_TOOSMALL="Size of boot partition is too small for update!"
  MSG_ERROR_TOOSMALL="Overlay size is too small!\n(minimum 400MB required)"
  MSG_ERROR_CANNOT_MOUNT_OVERLAY="Cannot mount overlay from target device!\nWrong password?"
  MSG_ADD_CUSTOM="Would you like to remaster Knoppix?\n\nAll changes versus the original will be added as a new, compressed image in the newly created copy.\n\nWarning: This includes your current network settings, personal data, browser history, passwords of the\nrunning system.\n\nThe compression process may take a long time,\nand needs about %d MB RAM.\nFor the additional image, additional %d MB space\nwill be reserved on the first partition. (You can\nstill further increase partition size.)"
  MSG_ADD_CUSTOM_WAIT="Collecting and compressing %d MB changed data,\nthis may take a long time.\n\nPlease don't change anything during this process\n(better: do nothing until this dialog disappears)."
  ERROR_ADD_CUSTOM="Error while remastering"
  MSG_ADD_CUSTOM_ERROR="Something went wrong (maybe disk full?).\nPlease check the protocol:"
;;
esac

TMP="/tmp/flash-knoppix.$$.tmp"
TMPMOUNT="/tmp/flash-knoppix.$$.tmpmount"
TMPMOUNT2="/tmp/flash-knoppix.$$.tmpmount2"
TMPSRCMOUNT="/tmp/flash-knoppix.$$.src.tmpmount"
PARTTYPE=msdos
CDR_DEVICE=""

# PARTTYPE=gpt

MINIMAL_IMAGE=""

FLASH=""
MAPDEV="home$$"

TITLE="flash-knoppix"

if [ -n "$DISPLAY" ] && type -p zenity >/dev/null 2>&1; then
 ICON="/usr/share/icons/flash-knoppix.xpm"
 [ -r "$ICON" ] && ICON="--window-icon=$ICON" || ICON=""
fi

# dialog_yesno title info
function dialog_yesno(){
 local title="$1" info="$2"; shift; shift
 if [ -n "$DISPLAY" ]; then
  zenity $ICON --question "$@" --no-wrap --width=600 --title="$title" --text="$info" 1>&2 2>/dev/null
 else
  dialog --backtitle "$TITLE" --title "$title" --yesno "$info" 23 75
 fi
}

# dialog_info title info
function dialog_info(){
 local title="$1" info="$2"
 if [ -n "$DISPLAY" ]; then
  zenity $ICON --info --no-wrap --width=600 --title="$title" --text="$info" 1>&2 2>/dev/null
 else
  dialog --backtitle "$TITLE" --title "$title" --msgbox "$info" 23 65
 fi
}

# dialog_info_timeout title info
function dialog_info_timeout(){
 local title="$1" info="$2"
 if [ -n "$DISPLAY" ]; then
  zenity $ICON --timeout=5 --info --no-wrap --width=600 --title="$title" --text="$info" 1>&2 2>/dev/null
 else
  dialog --timeout 5 --backtitle "$TITLE" --title "$title" --msgbox "$info" 23 65
 fi
}

# dialog_scale title info [min [max [current]]]
function dialog_scale(){
 local title="$1" info="$2" min="$3" max="$4" current="$5"
 if [ -n "$DISPLAY" ]; then
  zenity $ICON --scale --width=550 --title="$title" --text="$info" --min-value="$min" --max-value="$max" --step=50 --value="$current" 1>&2 2>/dev/null
 else
  dialog --backtitle "$TITLE" --title "$title" --inputbox "$info" 23 75 "$current"
 fi
}

function overlay_size(){
 if [ -d /KNOPPIX-DATA/home/knoppix ]; then
  df -m "/KNOPPIX-DATA/" | awk '{size=$(NF-3)}END{print size}'
 elif [ -d /ramdisk/home/knoppix ]; then
  df -m "/ramdisk/" | awk '{size=$(NF-3)}END{print size}'
 else
  return 1
 fi
 return 0
}

function dialog_minimal(){
 if dialog_yesno "$MSG_MINIMAL" "$MSG_MINIMAL_DESC" ; then
  MINIMAL_IMAGE="true"
 fi
}

function dialog_remaster(){
 local osize="$(overlay_size)"
 [ "$osize" -ge 1 ] 2>/dev/null || return 1
 local isize="$((osize / 2))"
 if dialog_yesno "Remaster" "$(printf "$MSG_ADD_CUSTOM" "$isize" "$isize")" ; then
  ADD_IMAGE="true"
 fi
}

function dialog_password(){
 local title="$1" info="$2"
 if [ -n "$DISPLAY" ]; then
  zenity $ICON --entry --width=550 --title="$title" --text="$info" 1>&2 2>/dev/null
 else
  dialog --backtitle "$TITLE" --title "$title" --inputbox "$info" 23 75 "$5"
 fi
}

# dialog_error title info
function dialog_error(){
 local title="$1" info="$2"
 if [ -n "$DISPLAY" ]; then
  zenity $ICON --error --no-wrap --width=600 --title="$title" --text="$info" 1>&2 2>/dev/null
 else
  dialog --backtitle "$TITLE" --title "$title" --msgbox "$info" 23 65
 fi
}

# dialog_error_file title info file
function dialog_error_file(){
 local title="$1" info="$2" file="$3"
 if [ -n "$DISPLAY" ]; then
  zenity $ICON --text-info --no-wrap --width=600 --title="$title" --text="$info" --filename="$file" 1>&2 2>/dev/null
 else
  dialog --backtitle "$TITLE" --title "$title" --textbox "$file" 23 65
 fi
}

# dialog_menu title wrapped_text menuitem1 description1 ...
function dialog_menu(){
 local title="$1" info="$2"
 shift 2
 if [ -n "$DISPLAY" ]; then
  for item in "$@"; do echo "$item"; done | { zenity $ICON --list --width=550 --height=280 --hide-header --title="$title" --text="$info" --column="" --column="" 1>&2 2>/dev/null; }
 else
  dialog --backtitle "$TITLE" --title "$title" --menu "$info" 23 75 8 "$@"
 fi
}

# dialog_progress title info
function dialog_progress(){
 local title="$1" info="$2" cancel="$3"
 shift 2
 [ -n "$cancel" ] && no_cancel="" || no_cancel="--no-cancel"
 if [ -n "$DISPLAY" ]; then
  zenity $ICON --progress --width=550 --title="$title" --auto-close ${no_cancel} --text="$info" 2>/dev/null
 else
  dialog --backtitle "$TITLE" --title "$title" --gauge "$info" 23 75 8 "$@"
 fi
}

# dialog_gauge title info
function dialog_gauge(){
 local title="$1" info="$2"
 shift 2
 if [ -n "$DISPLAY" ]; then
  zenity $ICON --progress --width=550 --title="$title" --auto-close --no-cancel --pulsate --text="$info" 2>/dev/null
 else
  dialog --backtitle "$TITLE" --title "$title" --gauge "$info" 23 75 8 "$@"
 fi
}

# dialog_dselect title info
function dialog_dselect(){
 local title="$1" info="$2"
 if [ -n "$DISPLAY" ]; then
  zenity $ICON --file-selection --filename=. --directory --width=550 --title="$title" 1>&2 2>/dev/null
 else
  dialog --backtitle "$TITLE" --title "$title" --dselect . 23 75
 fi
}

# dialog_options title info checked1 option1 checked2 option2 ...

# zenity --list --checklist --hide-header --text="Bitte Option angeben:" --column=option --column=beschreibung TRUE Eins FALSE Zwei TRUE Drei
function dialog_options(){
 local title="$1" info="$2"
 shift 2
 if [ -n "$DISPLAY" ]; then
  for item in "$@"; do echo "$item"; done | { zenity $ICON --list --checklist --width=550 --height=280 --hide-header --title="$title" --text="$info" --column="" --column="" 1>&2 2>/dev/null; }
 else
  dialog --backtitle "$TITLE" --title "$title" --menu "$info" 23 75 8 "$@"
 fi
}

ERROR=""

bailout(){
 killgauge
 cd $HOME
 umount "$TMPMOUNT" 2>/dev/null
 umount -d "$TMPMOUNT2" 2>/dev/null
 umount -d "$TMPSRCMOUNT" 2>/dev/null
 for i in /dev/loop*; do losetup -d "$i"; done >/dev/null 2>&1
 /sbin/cryptsetup remove "$MAPDEV" >/dev/null 2>&1
 # eject "$FLASH" 2>/dev/null
 rmdir "$TMPMOUNT" 2>/dev/null
 rmdir "$TMPSRCMOUNT" 2>/dev/null
 case "$1" in
  0) # Normal end of program
   dialog_info "$TITLE" "$DEVICE_INFO\n\n$MSG_READY";;
  1) # Cancel with no message
   true;;
  *) # Error
   dialog_error "$TITLE" "$DEVICE_INFO\n\n$ERROR";;
 esac
 rm -f "$TMP" "$TMP.done" "$TMP.err"
 exit $1
}

# progress info total_size_KB destination-files-or-dirs...
# a real size based progress bar
function progress(){
 local info="$1" total_size="$2"; shift 2
 if ! [ -n "$total_size" -a "$total_size" -gt 0 ]; then
  total_size=4000000
 fi
 rm -f "$TMP.done"
 while [ ! -e "$TMP.done" ]; do
  du -sk "$@" 2>/dev/null | awk '{size+=$1}END{print int(size * 100 / '"$total_size"')}'
  sleep 1
 done | dialog_progress "$TITLE" "$info" &
}

# gauge 
function gauge(){
 rm -f "$TMP.done"
 status=0
 while [ ! -e "$TMP.done" ]; do echo "$((status / 100))" ; status="`expr \( 10000 - $status \) / 100 + $status`"; sleep 1; done | dialog_gauge "$TITLE" "$1" &
}

# Stop status bar
function killgauge(){
 touch "$TMP.done" ; wait ; rm -f "$TMP.done"
}

# Unused
function mkefi_img(){
 efi_src="$SRC/efi"
 efi_dir="/tmp/efi.$$"
 efi_img="$efi_dir.img"
 umount "$efi_dir" >/dev/null 2>&1 && sleep 2
 rm -rf "$efi_dir" "$efi_img"
 mkdir "$efi_dir"
 dd if=/dev/zero of="$efi_img" bs=1M count=15
 mkdosfs -n UEFI "$efi_img"
 mount -o loop,rw,umask=000 "$efi_img" "$efi_dir"
 cp -r "$efi_src" "$efi_dir"/
 mkdir -p "$efi_dir"/boot/syslinux && cp -r "$SRC"/boot/isolinux/linux* "$SRC"/boot/isolinux/minirt.gz "$SRC"/boot/isolinux/syslnx*.cfg "$SRC"/boot/isolinux/f? "$SRC"/boot/isolinux/bootefi.msg "$SRC"/boot/isolinux/german.kbd "$efi_dir"/boot/syslinux/
 sleep 2
 sudo umount "$efi_dir"
 rm -rf "$efi_dir"
}

function get_burn_info(){
# CDR_DEVICE="$(wodim --devices | awk '/dev=/{sub(/dev=/,""); gsub(/'"'"'/,""); print $2; exit 0}')"
 CDR_DEVICE="$(xorriso -devices 2>/dev/null | awk '/^[0-9]/{gsub(/'"'"'/,""); print $3; exit 0}')"
 [ -n "$CDR_DEVICE" ] || return 1
}

# Creates an ISO image and sends it to the default DVD/CD-burner on-the-fly
# Needs xorriso and wodim
function burn(){
 EXCLUDE=""
 if [ -n "$MINIMAL_IMAGE" ]; then
  for i in "$SRC"/KNOPPIX/KNOPPIX?* "$SRC"/KNOPPIX/bootonly*; do
   [ -r "$i" ] && EXCLUDE="$EXCLUDE -m $i"
  done
 fi

 if ! dialog_yesno "$MSG_BURN" "$MSG_START_BURN"; then
	 bailout 0
 fi

 gauge "$MSG_BURNING"
 # xorriso/mkisofs need to modify isolinux/isolinux.bin, so we have to
 # add a ramdisk overlay in order to avoid modification of the original
 CDTMP="/tmp/cd.$$.tmp"; mkdir -p "/tmp/cd.$$.tmp"
 mount -t aufs -o br="$CDTMP"=rw:"$SRC"=ro cdtmp "$SRC" || return 1
 if [ -L "$SRC"/boot/isolinux -o ! -d "$SRC"/boot/isolinux ]; then
  rm -f "$SRC"/boot/isolinux || true
  mv -f "$SRC"/boot/syslinux "$SRC"/boot/isolinux
  mv -f "$SRC"/boot/isolinux/syslinux.cfg $SRC"/boot/isolinux/isolinux.cfg
  [ -e "$SRC"/boot/isolinux/isolinux.bin ] || cp /usr/local/lib/isolinux.bin $SRC"/boot/isolinux/ || true
 fi
 DST=""
 if [ -n "$FLASH" ]; then
  BURNOPTS=""
  OUTOPTS="-o $FLASH"
 else
  BURNOPTS="-blank as_needed -close on -commit-eject all"
  [ -n "$CDR_DEVICE" ] && BURNOPTS="-outdev $CDR_DEVICE $BURNOPTS"
  OUTOPTS=""
 fi

 echo "BURNOPTS: $BURNOPTS"
 echo "OUTOPTS: $OUTOPTS"

 # Since the user can choose flash-knoppix to write a DVD/CD or flash version,
 # we don't use the confusing duplicate EFI directory/partition hybrid boot trick here.
 xorriso \
  $BURNOPTS \
  -compliance iso_9660_level=3 \
  -boot_image isolinux dir=/boot/isolinux \
  -as mkisofs -l -r -J \
  -iso-level 3 \
  -V "KNOPPIX" -A "KNOPPIX" \
  -no-emul-boot \
  -hide-rr-moved \
  $EXCLUDE \
  $OUTOPTS "$SRC" ; RC="$?"
  sleep 2
  umount "$SRC"
  killgauge
  return "$RC"
}

DEVICE_VENDOR=""
DEVICE_MODEL=""
DEVICE_SIZE=""
DEVICE_DEV=""
DEVICE_INFO=""
FAT_EXISTS=""
KNOPPIX_EXISTS=""
OVERLAY_EXISTS=""
OVERLAY_PARTITION=""
OVERLAY_ENCRYPTED=""

# waitdev /dev/sdb1 - delay for a while waiting for partition to reappear
function waitdev(){
 for t in 1 2 3 4; do
  sleep 2
  [ -b "$1" ] && break
 done
}
 
# getstatus /dev/device - reports current flash disk status in variables
function getstatus(){
 local dev="${1##*/}"
 DEVICE_DEV="$1"
 DEVICE_VENDOR="$(cat /sys/block/$dev/device/vendor 2>/dev/null)"
 DEVICE_INFO="$dev:"
 [ -n "$DEVICE_VENDOR" ] && DEVICE_INFO="$DEVICE_INFO $(echo $DEVICE_VENDOR)"
 DEVICE_MODEL="$(cat /sys/block/$dev/device/model 2>/dev/null)"
 [ -n "$DEVICE_MODEL" ] && DEVICE_INFO="$DEVICE_INFO $(echo $DEVICE_MODEL)"
 DEVICE_SIZE="$(awk '{print ($1 / 2048)}' /sys/block/$dev/size 2>/dev/null)"
 [ -n "$DEVICE_SIZE" ] && DEVICE_INFO="$DEVICE_INFO ($(echo "${DEVICE_SIZE}MB"))"
 [ "$DEVICE_SIZE" -lt 10 ] >/dev/null 2>&1 || DEVICE_SIZE=0
 mkdir -p "$TMPMOUNT"
 mount -r -t vfat -o shortname=winnt "${1}1" "$TMPMOUNT" >/dev/null 2>&1
 sleep 1
 if mountpoint -q "$TMPMOUNT"; then
  FAT_EXISTS="true"
  if [ -r "$TMPMOUNT"/KNOPPIX/KNOPPIX ]; then
   KNOPPIX_EXISTS="true"
   local ext
   for ext in aes img inf; do
    local datafile="$TMPMOUNT/KNOPPIX/knoppix-data.$ext"
    if [ -r "$datafile" ]; then
     local mp="" fs="" opts=""
     OVERLAY_EXISTS="$ext"
     if [ "$ext" = "inf" ]; then
      while read OVERLAY_PARTITION mp fs opts; do
       if [ -z "$mp" -o "$mp" = "/KNOPPIX-DATA" -o "$mp" = "KNOPPIX-DATA" ]; then
        case "$opts" in *encryption*) OVERLAY_ENCRYPTED="true" ;; esac
        break
       else
        OVERLAY_PARTITION=""
       fi
      done < "$datafile"
     elif [ "$ext" = "aes" ]; then
      OVERLAY_ENCRYPTED="true"
     fi
     break
    fi
   done
  fi
  umount "$TMPMOUNT" >/dev/null 2>&1
 fi
}

function read_method(){
 local TEXT="$DEVICE_INFO\n"
 [ -n "$FAT_EXISTS" ] && TEXT="${TEXT}\n${MSG_FAT_EXISTS} ${DEVICE_DEV}1"
 [ -n "$KNOPPIX_EXISTS" ] && TEXT="${TEXT}\n${MSG_KNOPPIX_EXISTS} ${DEVICE_DEV}1"
 case "$OVERLAY_EXISTS" in
  img) TEXT="${TEXT}\n${MSG_OVERLAY_IMAGE_EXISTS}" ;;
  aes) TEXT="${TEXT}\n${MSG_ENCRYPTED_OVERLAY_IMAGE_EXISTS}" ;;
  inf) TEXT="${TEXT}\n${MSG_OVERLAY_PARTITION_EXISTS}" ;;
 esac
 TEXT="${TEXT}\n\n$MSG_METHOD_SELECT"
 local LIST=( "p" "$METHOD_NEW_PARTITION" "i" "$METHOD_NEW_IMAGE" "n" "$METHOD_NOTHING" )
 rm -f "$TMP"
 dialog_menu "$TITLE" "$TEXT" "${LIST[@]}" 2>"$TMP" || { rm -f "$TMP"; return 1; }
 read "$1" <"$TMP"; rm -f "$TMP"
}

function read_update(){
 local TEXT="$DEVICE_INFO\n"
 [ -n "$FAT_EXISTS" ] && TEXT="${TEXT}\n${MSG_FAT_EXISTS} ${DEVICE_DEV}1"
 [ -n "$KNOPPIX_EXISTS" ] && TEXT="${TEXT}\n${MSG_KNOPPIX_EXISTS} ${DEVICE_DEV}1"
 case "$OVERLAY_EXISTS" in
  img) TEXT="${TEXT}\n${MSG_OVERLAY_IMAGE_EXISTS}" ;;
  aes) TEXT="${TEXT}\n${MSG_ENCRYPTED_OVERLAY_IMAGE_EXISTS}" ;;
  inf) TEXT="${TEXT}\n${MSG_OVERLAY_PARTITION_EXISTS}" ;;
 esac
 TEXT="${TEXT}\n\n$MSG_UPDATE_SELECT"
 local LIST=( "h" "$MSG_UPDATE_CLEAN" "a" "$MSG_UPDATE_KEEP" "n" "$MSG_UPDATE_DELETE" )
 rm -f "$TMP"
 dialog_menu "$TITLE" "$TEXT" "${LIST[@]}" 2>"$TMP" || { rm -f "$TMP"; return 1; }
 read "$1" <"$TMP"; rm -f "$TMP"
}

function intro_read_allow_hd(){
 local LIST=("r" "$MSG_NOALLOWHD" "h" "$MSG_ALLOWHD" "c" "$MSG_BURN")
 rm -f "$TMP"
 dialog_menu "$TITLE" "$MSG_INTRO" "${LIST[@]}" 2>"$TMP" || { rm -f "$TMP"; return 1; }
 read "$1" <"$TMP"; rm -f "$TMP"
}

# setup_loop file_or_blockdevice [encrypted]
# Returns true and saves loopback device in global variable LOOP
# expects password from stdin
function setup_loop(){
 LOOP=""
 LOOP="$(/sbin/losetup -f 2>>"$TMP.err")"
 if [ -n "$2" ]; then # Encrypted
  local m mods=""
  for m in loop cryptoloop aes_generic aes_i586 cbc; do
   [ -d /sys/module/"$m" ] || mods="$mods $m"
  done
  [ -n "$mods" ] && /sbin/modprobe $mods >/dev/null 2>&1
  tr -d '\n\r' | /sbin/cryptsetup create --key-size 256 --key-file - --cipher aes "$MAPDEV" "$1"
  # /sbin/losetup -p 0 -e aes -k 256 "$LOOP" "$1" 2>>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
 else # No encryption
  /sbin/losetup "$LOOP" "$1" 2>>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
 fi
 return 0
}

function usage(){
 echo "Usage: $0 [-a] [-f] [-m i|p|n] [-p mb] [image.iso|dir] [target_device]" >&2
 echo "       -a            Allow fixed disks" >&2
 echo "       -f            Force overwrite, no questions (batch mode)" >&2
 echo "       -m i          Method: Create overlay image" >&2
 echo "       -m p          Method: Create overlay partition (recommended)" >&2
 echo "       -m n          Method: No overlay (read only)" >&2
 echo "       -p mb         Overlay partition or image size in MB >= 200"  >&2
 echo "       -r            Remaster (create new compressed overlay with changes)"  >&2
 echo "       -s            Reduce to Small (CD sized) image < 700MB"  >&2
 echo "       -b            Burn CD/DVD instead of flashing"  >&2
 echo "       image.iso     Loopmount source ISO file" >&2
 echo "       dir           Source data directory containing files" >&2
 echo "       target_device Destination block device (flash disk / DVD recorder)"  >&2
 exit 1
}

function create_image(){
 local src=""
 local rc=0
 if [ -d /KNOPPIX-DATA/home/knoppix ]; then
  src="/KNOPPIX-DATA/"
 elif [ -d /ramdisk/home/knoppix ]; then
  src="/ramdisk/"
 else
  return 1
 fi
 local nr
 for nr in 1 2 3 4 5 6 7; do
   [ -r "$TMPMOUNT/KNOPPIX/KNOPPIX$nr" ] || break
 done
 [ "$nr" -le 7 ] 2>/dev/null || return 1
 local dest="$TMPMOUNT/KNOPPIX/KNOPPIX$nr"
 local osize="$(overlay_size)"
 ( cd "$src"; mkisofs -input-charset default -no-split-symlink-components -no-split-symlink-fields -V KNOPPIX_EXTRAS$nr  -hide-rr-moved -cache-inodes -pad -l -R -U -v \
-m tmp/\* \
-m var/cache/apt\* \
-m var/cache/man\* \
-m var/log/\* \
-m var/run/\* \
-m var/lib/dpkg/lock\* \
-m var/lib/NetworkManager/\* \
. | create_compressed_fs -L -2 -B 131072 -m - "$dest" ) 2>&1 | tee "$TMP.err" | awk '/% done/{print substr($1,0,2)}' | dialog_progress "Remaster" "$(printf "$MSG_ADD_CUSTOM_WAIT" "$osize")" "true"
 rc="$?"
 case "$rc" in
  0) rm -f "$TMP.err";;
  *) dialog_error_file "$ERROR_ADD_CUSTOM" "$MSG_ADD_CUSTOM_ERROR" "$TMP.err"; rm -f "$TMP.err" "$dest"; return 1;;
 esac
 return 0
}

### MAIN ###

[ "`id -u`" != "0" ] && exec sudo "$0" "$@"

unset SUDO_COMMAND
ALLOWHD=""
SIZE=""
FORCE=""
METHOD=""
ADD_IMAGE=""
INCLUDE_PERSONAL=""
# Ask for method, i=overlay image, p=overlay partition

# Parse options
while [ -n "$1" ]; do
 case "$1" in
  --help|-h) usage ;;
  -a) ALLOWHD="true" ;;
  -f) FORCE="true" ;;
  -m) shift; case "$1" in i|p|n) METHOD="$1";; *) usage;; esac ;;
  -p) shift; [ "$1" -ge 200 ] && SIZE="$1" ;;
  -s) MINIMAL_IMAGE="true";;
  -b) BURN_IMAGE="true";;
   *) # ISO file, SRC dir or destination device
     if [ -b "$1" ]; then # Block device, destination
      FLASH="$1"
     elif [ -r "$1" ]; then # It may be an ISO, mount it.
      mkdir -p "$TMPSRCMOUNT"
      mount -o loop,ro "$1" "$TMPSRCMOUNT" && cd "$TMPSRCMOUNT"
     elif [ -d "$1" ]; then
      cd "$1"
     else
      if [ -n "$BURN_IMAGE" -a ! -f "$1" ]; then
       FLASH="$1"
      else
       usage
      fi
     fi
     ;;
  -i)  ADD_IMAGE="true" ;;
 esac
 shift || break
done
 
if [ ! -n "$FLASH" -o ! -b "$FLASH" ]; then
 if [ -z "$ALLOWHD" -a -z "$BURN_IMAGE" ]; then
  intro_read_allow_hd hd || bailout 1
  case "$hd" in
   h) ALLOWHD="true";;
   c) if get_burn_info; then
       BURN_IMAGE="true"
      else
       ERROR="$MSG_ERROR_NOCD"
       bailout 2
      fi ;;
   *) ALLOWHD="";;
  esac
 fi
 if [ -z "$BURN_IMAGE" ]; then
  DEVICELIST=()
  count=0
  for i in $(ls -1d /sys/block/sd? /sys/block/mmcblk? 2>/dev/null); do
   device="${i##/sys/block/}"
   # Safety check
   if [ "$(cat /sys/block/$device/removable)" = "0" ] && [ -z "$ALLOWHD" -a -z "$FORCE" -a -z "$OVERRIDE" ]; then
    # This is a fixed disk!
    continue
   fi
   # Don't show the USB stick we are running from
   # Hey Mike McC., thanks for the hint about fixing the device name pattern here! :-)
   grep -q "${device}[0-9]* .*/mnt-system" /proc/mounts && continue
   DEVICELIST[$((count++))]="$device"
   DEVICELIST[$((count++))]="$(cat $i/device/vendor 2>/dev/null) $(cat $i/device/model 2>/dev/null) ($(awk '{print ($1 / 2048) "MB"}' $i/size 2>/dev/null))"
  done
  rm -f "$TMP"
  if [ -n "${DEVICELIST[*]}" ]; then
   while ! [ -b "$FLASH" ]; do
    dialog_menu "$TITLE" "
$MSG_TARGET
" "${DEVICELIST[@]}" 2>"$TMP" || bailout 1
    read FLASH <"$TMP"; rm -f "$TMP"
    FLASH="/dev/$FLASH"
   done
  else
   ERROR="$MSG_ERROR_NODISK"
   bailout 2
  fi
 fi
fi

if [ -z "$BURN_IMAGE" ] && grep -q "^${FLASH}" /proc/mounts && ! umount "${FLASH}1"; then
 ERROR="$FLASH $MSG_MOUNTED"
 bailout 2
fi

if [ ! -r KNOPPIX/KNOPPIX -a -r /mnt-system/KNOPPIX/KNOPPIX ]; then
 SRC=/mnt-system
 cd "$SRC"
else
 while [ ! -r KNOPPIX/KNOPPIX ]; do
  dialog_dselect "$MSG_SELECT" "$MSG_SELECT" 2>"$TMP" || bailout 1
  SRC="$(<$TMP)"
  [ -d "$SRC" ] && cd "$SRC"
 done
fi

if [ -z "$BURN_IMAGE" ]; then
 # Get flash status
 gauge "$MSG_CHECKING $FLASH..."
 getstatus "${FLASH}"
 killgauge
fi

UPDATE=""
# If already installed, ask about update
if [ -z "$FORCE" ]; then
 if [ -n "$KNOPPIX_EXISTS" ]; then
  echo "Ask for update" >&2
  read_update UPDATE || bailout 1
 else
  dialog_minimal
 fi
fi

if [ -z "$BURN_IMAGE" ]; then
if [ -n "$UPDATE" -a "$UPDATE" != "n" ]; then
 METHOD="$UPDATE"
 # (Re-) check size of boot partition
 total="$(awk '{print int($1 / 2048)}' /sys/block/"${FLASH##*/}/${FLASH##*/}1"/size 2>/dev/null)"
 # Add 10% filesystem overhead
 ksize="$(du -sm --exclude='knoppix-data.*' . 2>/dev/null | awk '{size=$1}END{print int(size*1.1)}')"
 let avail=total-ksize
 if [ "$avail" -lt 100 ]; then
  ERROR="${FLASH}1:\n$MSG_ERROR_BOOT_TOOSMALL"
  bailout 2
 fi
elif [ -z "$METHOD" ]; then
 echo "Ask for install method" >&2
 # Ask for method, i=overlay image, p=overlay partition n=likeDVD
 while true; do
  read_method METHOD || bailout 1
  [ -n "$METHOD" ] && break
 done
fi
fi

mkdir -p "$TMPMOUNT"

# Use ionice, be friendly to our multitasking
IONICE=""
type -p ionice >/dev/null 2>&1 && IONICE="ionice -c 3"

# If the user selected "burn a CD", only call burn() and skip the rest!
if [ -n "$BURN_IMAGE" ]; then
 echo "Burning CD/DVD" >&2
 burn
 if [ "$?" != 0 ]; then
  ERROR="Burning failed."; bailout 2
 fi
 bailout 0
fi

echo "Ask for partitioning" >&2
if [ "i" = "$METHOD" -o "n" = "$METHOD" ]; then
 # Overlay image or "no overlay" method selected
 if [ -n "$FORCE" ] || { dialog_yesno "$TITLE" "$DEVICE_INFO\n\n$MSG_QUESTION_PARTITION" && dialog_yesno "$TITLE" "$DEVICE_INFO\n\n$MSG_QUESTION_REALLY_FORMAT"; }; then
  gauge "$DEVICE_INFO\n\n$MSG_PARTITION $FLASH..."
  dd if=/dev/zero of="$FLASH" bs=4M count=1 >/dev/null 2>&1
  blockdev --flushbufs "$FLASH"
  parted "$FLASH" 2>"$TMP.err" <<EOT
mktable $PARTTYPE
mkpart primary fat32 2048s -0
set 1 boot on
quit
EOT
#  sfdisk -u M "$FLASH" 2>"$TMP.err" <<EOT
#,,c,*
#EOT
  if [ "$?" != 0 ]; then
   ERROR="$(<$TMP.err)"; bailout 2
  fi
  rm -f "$TMP.err"
  blockdev --flushbufs "$FLASH"
  sleep 10
  # udev may need some additional time to settle down after repartitioning
  udevadm settle --timeout=20
  waitdev "${FLASH}1"
  $IONICE mkdosfs -F32 -n "KNOPPIX" "${FLASH}1" 2>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
  $IONICE blockdev --flushbufs "${FLASH}1"
  killgauge
 elif [ -n "$FAT_EXISTS" ]; then # FAT exists -> just set bootable later
  MAKE_BOOTABLE="true"
 else # fail
  ERROR="${FLASH}:\n$MSG_ERROR_INCOMPATIBLE"; bailout 2
 fi
 [ -n "$FORCE" -o -n "$MINIMAL_IMAGE" ] || dialog_remaster
elif [ "p" = "$METHOD" ]; then
 [ -n "$FORCE" ] || dialog_remaster
 total="$(awk '{print int($1 / 2048)}' /sys/block/"${FLASH##*/}"/size 2>/dev/null)"
 # Add 10% filesystem overhead
 if [ -n "$MINIMAL_IMAGE" ]; then
  ksize="$(du -sm --exclude='knoppix-data.*' --exclude='KNOPPIX[1-9]*' . 2>/dev/null | awk '{size=$1}END{print int(size*1.1)}')"
 else
  ksize="$(du -sm --exclude='knoppix-data.*' . 2>/dev/null | awk '{size=$1}END{print int(size*1.1)}')"
 fi
 let avail=total-ksize
 let avail-=200
 if [ -n "$ADD_IMAGE" ]; then
  let avail-="$(overlay_size)"
 fi
 if [ "$avail" -lt 400 ]; then
  ERROR="${FLASH}:\n$MSG_ERROR_TOOSMALL"
  bailout 2
 fi
 if [ -n "$FORCE" ] || { dialog_yesno "$TITLE" "$DEVICE_INFO\n\n$MSG_QUESTION_PARTITION_ADVANCED" && dialog_yesno "$TITLE" "$DEVICE_INFO\n\n$MSG_QUESTION_REALLY_FORMAT"; }; then
  if [ -z "$SIZE" ]; then
   rm -f "$TMP"
   dialog_scale "$TITLE" "$(printf "$MSG_SIZE_OVERLAY_ADVANCED" "$avail")" 400 "$avail" "$avail" 2>"$TMP" || bailout 1
   read SIZE <"$TMP"
   [ "$SIZE" -ge 400 ] 2>/dev/null || SIZE="400"
  fi
  [ "$SIZE" -gt "$avail" ] && SIZE="$avail"
  gauge "$DEVICE_INFO\n$MSG_PARTITION $FLASH..."
  dd if=/dev/zero of="$FLASH" bs=4M count=1 >/dev/null 2>&1
  blockdev --flushbufs "$FLASH"
  parted "$FLASH" 2>"$TMP.err" <<EOT
mktable $PARTTYPE
mkpart primary fat32 2048s $((total-SIZE))M
set 1 boot on
mkpart primary reiserfs $((total-SIZE))M -0
quit
EOT
#  sfdisk -u M "$FLASH" 2>"$TMP.err" <<EOT
#,$((total-SIZE)),c,*
#,,83,
#EOT
  if [ "$?" != 0 ]; then
   ERROR="$(<$TMP.err)"; bailout 2
  fi
  rm -f "$TMP.err"
  blockdev --flushbufs "$FLASH"
  sleep 10
  # udev may need some additional time to settle down after repartitioning
  udevadm settle --timeout=20
  waitdev "${FLASH}1"
  killgauge
  gauge "$DEVICE_INFO\n$MSG_FORMAT $FLASH partition 1..."
  $IONICE mkdosfs -F32 -n "KNOPPIX" "${FLASH}1" 2>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
  $IONICE blockdev --flushbufs "${FLASH}1"
  killgauge
 else
  bailout 1
 fi
fi

echo "(Re-)create boot loader, first remove the old one" >&2
# (Re-)create boot loader, first remove the old one
gauge "$DEVICE_INFO\n$MSG_BOOTREC $FLASH..."
rm -f "$TMP.err"
waitdev "${FLASH}1"
mount -t vfat -o shortname=winnt "${FLASH}1" "$TMPMOUNT" 2>"$TMP.err" || { killgauge; ERROR="${FLASH}:\n$MSG_ERROR_INCOMPATIBLE"; bailout 2; }
[ -f "$TMPMOUNT"/ldlinux.sys ] && rm -f "$TMPMOUNT"/ldlinux.sys
blockdev --flushbufs "${FLASH}1"
sleep 2
umount "$TMPMOUNT"
rm -f "$TMP.err"
syslinux "${FLASH}1" 2>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
blockdev --flushbufs "${FLASH}1"
sleep 2
killgauge

echo "Mount boot partition" >&2
if [ -r boot/syslinux/syslinux.cfg -o -r boot/isolinux/isolinux.cfg ]; then
 waitdev "${FLASH}1"
 mount -t vfat -o shortname=winnt "${FLASH}1" "$TMPMOUNT" 2>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }

 # Update methods
 if [ "$METHOD" = "h" -a -n "$OVERLAY_EXISTS" ]; then
  # Need to mount overlay image or partition and delete all but home
  echo "Mount KNOPPIX overlay" >&2
  mkdir -p "$TMPMOUNT2"
  while true; do # Stay here until mount of overlay succeeds (never lose data)
   rm -f "$TMP"
   if [ -n "$OVERLAY_ENCRYPTED" ]; then
    dialog_password "$TITLE" "$MSG_PASSWORD" 2>"$TMP" || { rm -f "$TMP"; CRYPT=""; break; }
   else
    touch "$TMP"
   fi
   fs=auto
   case "$OVERLAY_EXISTS" in
    img|aes) setup_loop "$TMPMOUNT"/KNOPPIX/knoppix-data."$OVERLAY_EXISTS" "$OVERLAY_ENCRYPTED" <"$TMP"; fs=ext2;;
    inf)     setup_loop "${FLASH}$OVERLAY_PARTITION" "$OVERLAY_ENCRYPTED" <"$TMP"; fs=reiserfs;;
   esac
   if [ -n "$OVERLAY_ENCRYPTED" ]; then
    mount -t "$fs" /dev/mapper/"$MAPDEV" "$TMPMOUNT2" && break
   else
    mount -t "$fs" "$LOOP" "$TMPMOUNT2" && break
   fi
   dialog_info_timeout "$TITLE" "$DEVICE_INFO\n\n$MSG_ERROR_CANNOT_MOUNT_OVERLAY"
   [ -n "$OVERLAY_ENCRYPTED" ] || bailout 1
  done
  echo "Delete overlay data except /home" >&2
  for i in "$TMPMOUNT2"/* "$TMPMOUNT2"/.??*; do
   [ -e "$i" ] || continue
   case "$i" in */home|*/home/) true;; *) rm -rff "$i";; esac
  done
  sleep 2
  umount -d "$TMPMOUNT2" 2>/dev/null
  /sbin/cryptsetup remove "$MAPDEV" >/dev/null 2>&1
 fi

 echo "Now copy all the files (except for overlays)" >&2
 knoppix_src=()
 knoppix_dst=()
 knoppix_cnt=0
 while read name; do
  [ -r "$name" -o -d "$name" ] || continue
  # Skip knoppix-data.* and eventually files not included in minimal image
  case "$name" in
   KNOPPIX/[Kk][Nn][Oo][Pp][Pp][Ii][Xx]-[Dd][Aa][Tt][Aa].*) true;;
   KNOPPIX/[Kk][Nn][Oo][Pp][Pp][Ii][Xx][1-9]*|KNOPPIX/*.[Ii][Ss][Oo]*)
    if [ -z "$MINIMAL_IMAGE" ]; then
     knoppix_src[$knoppix_cnt]="$name"; knoppix_dst[$knoppix_cnt]="$TMPMOUNT/$name"
    fi;;
   *) knoppix_src[$knoppix_cnt]="$name"; knoppix_dst[$knoppix_cnt]="$TMPMOUNT/$name";;
  esac
  let knoppix_cnt++
 done <<.
$(ls -1d KNOPPIX/*)
.

 progress "$DEVICE_INFO\n$MSG_WRITING" $(du -sk boot efi "${knoppix_src[@]}" 2>/dev/null | awk '{size+=$1}END{print size}') "$TMPMOUNT/boot" "$TMPMOUNT/efi" "${knoppix_dst[@]}"
 [ "$METHOD" = "h" ] && rm -ff "$TMPMOUNT"/KNOPPIX/[Kk][Nn][Oo][Pp][Pp][Ii][Xx][0-9] 2>/dev/null
 $IONICE cp -Lrf boot "$TMPMOUNT"/ 2>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
 if [ -r index.html -a ! -e "$TMPMOUNT"/index.html ]; then
  $IONICE cp -Lf index.html "$TMPMOUNT"/ 2>/dev/null
 fi
 if [ -d efi ]; then
  $IONICE cp -Lrf efi "$TMPMOUNT"/ 2>/dev/null
 fi
 mkdir "$TMPMOUNT"/KNOPPIX 2>/dev/null
 $IONICE cp -Lrf "${knoppix_src[@]}" "$TMPMOUNT"/KNOPPIX/ 2>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
 if [ ! -r boot/syslinux/syslinux.cfg -a -r boot/isolinux/isolinux.cfg ]; then
  [  -d "$TMPMOUNT"/boot/syslinux ] && rm -rf "$TMPMOUNT"/boot/syslinux
  mv -f "$TMPMOUNT"/boot/isolinux "$TMPMOUNT"/boot/syslinux
  mv -f "$TMPMOUNT"/boot/syslinux/isolinux.cfg "$TMPMOUNT"/boot/syslinux/syslinux.cfg
  rm -f "$TMPMOUNT"/boot/syslinux/isolinux.* "$TMPMOUNT"/boot/syslinux/*.cat "$TMPMOUNT"/boot/isolinux.* "$TMPMOUNT"/boot/*.cat
 fi
 killgauge
else
 ERROR="$MSG_NOTFOUND"
 bailout 3
fi

if [ "$METHOD" = "n" -o "$UPDATE" = "n" ]; then
 rm -f "$TMPMOUNT"/KNOPPIX/knoppix-data.*
fi

if [ -n "$ADD_IMAGE" ]; then
 echo "Create new compressed image." >&2
 create_image
fi

# If we don't already have an overlay, ask to create one
if [ ! "$METHOD" = "n" -a ! -e "$TMPMOUNT"/KNOPPIX/knoppix-data.img -a ! -e "$TMPMOUNT"/KNOPPIX/knoppix-data.aes -a ! -e "$TMPMOUNT"/KNOPPIX/knoppix-data.inf ]; then
 if [ "i" = "$METHOD" ]; then # Image creation: Ask for size
  avail="$(df -m "$TMPMOUNT" | awk '{size=$(NF-2)}END{print size - 1}')"
  # At least 200MB, but not more than 4GB is allowed on a FAT32 file system
  [ "$avail" -ge 200 ] 2>/dev/null || bailout 0
  [ "$avail" -le 4000 ] || avail=4000
  rm -f "$TMP"
  if [ -z "$SIZE" ]; then
   dialog_scale "$TITLE" "$(printf "$MSG_SIZE_OVERLAY" "$avail")" 200 "$avail" "$avail" 2>"$TMP" || bailout 1
   read SIZE <"$TMP"
  fi
  [ "$SIZE" -ge 200 ] 2>/dev/null || SIZE="200"
  [ "$SIZE" -le 4000 ] 2>/dev/null || SIZE="$avail"
 else
  SIZE="$(awk '{print int($1 / 2048)}' /sys/block/"${FLASH##*/}"/"${FLASH##*/}2"/size 2>/dev/null)"
 fi
 if [ -z "$FORCE" ]; then
  dialog_yesno "$TITLE" "$MSG_CRYPT_OVERLAY" && CRYPT=yes || CRYPT=""
 fi
 if [ -n "$CRYPT" ]; then
  pw1=""; pw2=""; len=0
  while [ -z "$pw1" -o -z "$pw2" -o x"$pw1" != x"$pw2" -o "$len" -lt 4 ]; do
   rm -f "$TMP"
   [ -n "$pw1" ] && dialog_info_timeout "$TITLE" "$MSG_PASSWORDS_NOMATCH"
   dialog_password "$TITLE" "$MSG_PASSWORD" 2>"$TMP" || { rm -f "$TMP"; CRYPT=""; break; }
   read pw1 <"$TMP"; rm -f "$TMP"
   dialog_password "$TITLE" "$MSG_PASSWORD2" 2>"$TMP"
   read pw2 <"$TMP"; len="$(wc -c "$TMP" | awk '{print $1}')"
   # Don't delete $TMP yet, we need it for losetup
  done
 fi
 gauge "$DEVICE_INFO\n$(printf "$MSG_OVERLAY" "$SIZE")"
 if [ -n "$CRYPT" ]; then
  if [ "i" = "$METHOD" ]; then # Image creation: Create random data
   $IONICE dd if=/dev/urandom of="$TMPMOUNT"/KNOPPIX/knoppix-data.aes bs=1M count="$SIZE" >/dev/null 2>"$TMP.err"
   setup_loop "$TMPMOUNT"/KNOPPIX/knoppix-data.aes encrypted <"$TMP"
   rm -f "$TMP"
   $IONICE mke2fs -F -m 0 /dev/mapper/"$MAPDEV" 2>>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
   $IONICE blockdev --flushbufs /dev/mapper/"$MAPDEV"
   sleep 2
   /sbin/cryptsetup remove "$MAPDEV"
  elif [ "p" = "$METHOD" ]; then # Data partition
   # $IONICE dd if=/dev/urandom of="${FLASH}2" bs=1M >/dev/null 2>"$TMP.err"
   # Overwriting the entire partition with random data may be a waste of time,
   # so let's just format it.
   waitdev "${FLASH}2"
   setup_loop "${FLASH}2" encrypted <"$TMP"
   rm -f "$TMP"
   $IONICE mkreiserfs -s 513 -f -f -l "KNOPPIX-DATA" /dev/mapper/"$MAPDEV" 2>>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
   $IONICE blockdev --flushbufs /dev/mapper/"$MAPDEV"
   /sbin/cryptsetup remove "$MAPDEV"
   # Create fstab style entry
   echo "2 /KNOPPIX-DATA reiserfs encryption=aes" >> "$TMPMOUNT"/KNOPPIX/knoppix-data.inf
  fi
 else # No encryption
  if [ "i" = "$METHOD" ]; then
   $IONICE dd if=/dev/zero of="$TMPMOUNT"/KNOPPIX/knoppix-data.img bs=1M count="$SIZE" >/dev/null 2>"$TMP.err"
   $IONICE mke2fs -F -m 0 "$TMPMOUNT"/KNOPPIX/knoppix-data.img 2>>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
  elif [ "p" = "$METHOD" ]; then
   waitdev "${FLASH}2"
   $IONICE mkreiserfs -s 513 -f -f -l "KNOPPIX-DATA" "${FLASH}2" 2>>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
   $IONICE blockdev --flushbufs "${FLASH}2"
   echo "2 /KNOPPIX-DATA reiserfs" >> "$TMPMOUNT"/KNOPPIX/knoppix-data.inf
  fi
 fi
fi

# Flush and umount file system
blockdev --flushbufs "${FLASH}1"
sleep 2
umount "$TMPMOUNT"

# Create MBR
echo "Creating a master boot record" >&2
if [ "$PARTTYPE" = "msdos" ]; then
 # Don't depend on ms-sys
 # ms-sys -s "${FLASH}" 2>"$TMP.err" || { ERROR="$(<$TMP.err)"; bailout 2; }
 for mbr in /usr/lib/syslinux/mbr.bin /usr/lib/syslinux/mbr/mbr.bin; do
  [ -r "$mbr" ] || continue
  dd if="$mbr" of="${FLASH}" bs=440 count=1 && break
 done
elif [ "$PARTTYPE" = "gpt" ]; then
 for mbr in /usr/lib/syslinux/gptmbr.bin /usr/lib/syslinux/mbr/gptmbr.bin; do
  [ -r "$mbr" ] || continue
  dd if="$mbr" of="${FLASH}" bs=440 count=1 && break
 done
fi
blockdev --flushbufs "${FLASH}"
waitdev "${FLASH}1"

# Finally mark partition 1 as bootable, if not already done.
# this may cause another udev run, which we can ignore here
if [ -n "$MAKE_BOOTABLE" ]; then
 parted "$FLASH" 2>"$TMP.err" <<EOT
set 1 boot on
quit
EOT
 blockdev --flushbufs "${FLASH}"
fi

# Give block layer time to settle down
udevadm settle --timeout=20
sleep 4

bailout 0
