#! /bin/bash
#
# Copyright 2014-2016 Nio Wiklund
#
# GPLv3: GNU GPL version 3
# <http://gnu.org/licenses/gpl.html>.
#
# This is free software: you are free to change and redistribute it.
# There is NO WARRANTY, to the extent permitted by law.
#-----------------------------------------------------------------------------
# author sudodus alias nio-wiklund at launchpad
#
# date        editor   comment
# 2013-06-25  sudodus  linux installer from tarball of installed system
# 2013-06-27  sudodus  raring.tar.gz
# 2013-08-09  sudodus  removed lame logic for wipe as alternative to install
# 2013-09-22  sudodus  mktst selector introduced in mkusb
# 2013-09-24  sudodus  help text managed also for text screen
# 2013-09-26  sudodus  mktst selector tweaked for mkusb
# 2013-09-26  sudodus  mkusb cleaned, version 4.0
# 2013-11-17  sudodus  not only check also offer installation of pv
# 2013-11-22  sudodus  mkusb version 5.0
# 2014-01-06  sudodus  mkusb version 6.0 calls to sudo removed
# 2014-01-29  sudodus  identification of 'livedrive' fixed for live session
# 2014-01-29  sudodus  mkusb version 7.0
# 2014-01-30  sudodus  more livedrive fixes: CD, cloned iso, grub-n-iso,
#                      unetbootin, usb-creator-gtk
# 2014-01-30  sudodus  mkusb version 7.1
# 2014-03-06  sudodus  fix to recognize debian iso file and work from CD
# 2014-03-06  sudodus  mkusb version 7.2
# 2014-03-09  sudodus  second parameter 'all' to start seeing all drives
#                      usbonly=false
# 2014-03-09  sudodus  mkusb version 7.3
# 2014-03-13  sudodus  switch for help window
# 2014-03-14  sudodus  writing "Done" after installation (for xterm -hold) 
# 2014-03-14  sudodus  mkusb version 7.4
#
# 2014-08-01  sudodus  *** forking to mkusb-nox (alias version 7.5) ***
# 2014-08-02  sudodus  adding uncompressed image files for input (file.img)
# 2014-08-02  sudodus  function list_drives instead of parted and fdisk
# 2014-08-02  sudodus  function mkcmd_runcmd to improve iso identification
# 2014-08-02  sudodus  FINAL WARNING with inverse video added
# 2014-08-02  sudodus  help text removed, assuming advanced users
# 2014-08-02  sudodus  new usage text (from mkusb -h)
# 2014-08-02  sudodus  mkusb version 7.5
# 2014-09-07  sudodus  livedrive recognition debugged: grep -m 1 ...
# 2014-09-07  sudodus  skip if iso diskname matches on livedrive
# 2014-09-07  sudodus  mkusb version 7.5.1
# 2014-09-12  sudodus  livedrive recognition for mageia
# 2014-09-07  sudodus  mkusb version 7.5.2
# 2014-09-18  sudodus  livedrive recognition for knoppix
# 2014-09-18  sudodus  bugfix for diskname (from mkusb)
# 2014-09-18  sudodus  mkusb version 7.5.3
# 2014-09-20  sudodus  find_installer: finds and selects apt-get yum zypper urpmi
# 2014-09-25  sudodus  when identifying if iso testing: try to unmount partitions
#                      except swap partitions, and consider drives with an active
#                      swap partition busy, 'variable bizz'
# 2014-09-25  sudodus  function same_iso: separated from the main program
# 2014-09-25  sudodus  mkusb version 7.5.4
# 2014-11-19  sudodus  "Please wait for sync (flushing file system buffers
#                      to the device) until 'Done' is written ..."
# 2014-11-19  sudodus  mkusb version 7.5.5
# 2014-11-22  sudodus  cd to source file directory to keep partition mounted
# 2014-11-22  sudodus  mkusb version 7.5.6
# 2014-12-07  sudodus  final text for wipe-whole-device improved
# 2014-12-07  sudodus  mkusb version 7.5.7
# 2015-04-03  sudodus  current directory changed to that of the source file, so
#                      source=${source##*/} ... to manage path in parameter
# 2015-04-03  sudodus  clone a device (typically a CD drive or USB drive)
# 2015-04-03  sudodus  mkusb version 7.5.8
# 2015-06-21  sudodus  tries to unmount only usb drives when usbonly
#                      and does not try to unmount drives in fstab
# 2015-06-22  sudodus  livedrive=$(df |grep /$|cut -c 5-8)
# 2015-06-22  sudodus  mkusb version 7.5.9 <---> 9.2.1 GUI version
# 2015-08-01  sudodus  FINAL WARNING --> Final checkpoint
# 2015-08-01  sudodus  Do you really ... --> Please check ...
# 2015-08-01  sudodus  mkusb version 7.5.9.1 <---> 9.2.2 GUI version
# 2015-12-05  sudodus  grep -m1 in calculation of infstb (drive in fstab and busy)
# 2015-12-05  sudodus  mkusb version 7.5.9.2 <---> 10.4.2 GUI version
# 2016-04-11  sudodus  xz --robot --list
# 2016-04-11  sudodus  mkusb version 7.5.9.3 <---> 10.6.2 GUI version
# 2016-04-13  sudodus  mk_msdos to restore to a storage device
# 2016-04-13  sudodus  mkusb version 7.5.9.4 <---> 10.6.3 GUI version
# 2016-05-20  sudodus  fix to allow spaces and special characters in path
# 2016-05-20  sudodus  function gpt_fix
# 2016-05-20  sudodus  offer installation of gdisk (for gpt_fix)
# 2016-05-20  sudodus  mkusb version 7.5.9.5 <---> 10.6.4 GUI version
# 2016-05-24  sudodus  function gpt_zap
# 2016-05-24  sudodus  mkusb version 7.5.9.6 <---> 10.6.5 GUI version
# 2016-05-24  sudodus  improved logic to invoke gpt_fix
# 2016-05-24  sudodus  mkusb version 7.5.9.7 <---> 10.6.6 GUI version
# 2016-09-14  sudodus  fix to manage flash cards seen as /dev/mmcblk0
# 2016-09-14  sudodus  mkusb version 7.5.9.8 <---> 11.0.3 GUI version
# 2016-09-14  sudodus  rename: mkusb 7.5.9.8 ----> mkusb-nox 11.0.3
# 2016-09-14  sudodus  mkusb-nox version 11.0.{3,4}
# 2016-09-17  sudodus  lsblk -db ...: removed error output when no mmkblk?
# 2016-09-19  sudodus  mkusb-nox version 11.0.{5,6}
# 2016-09-20  sudodus  fix for opensuse 42.1:
#                      disk/by-id/ 'scsi' accepted because 'usb' not used
# 2016-09-20  sudodus  mkusb-nox version 11.0.{7,8}
# 2016-09-28  sudodus  added feature: make USB install drive for Windows
# 2016-09-28  sudodus  mkusb-nox version 11.1.0
# 2016-10-06  sudodus  debian: replaced rsync (not default) with cp and
#                      removed 'insmod' lines with grep -v for grub.cfg
#                      put debian 'on par' with ubuntu in text strings
# 2016-10-06  sudodus  mkusb-nox version 11.1.{1,2}
# 2016-10-16  sudodus  made mkusb-nox independent [of other files]:
#                      echo commands instead of grub-win-install.cfg
# 2016-10-16  sudodus  mkusb-nox version 11.1.{3,4}
# ----------------------------------------------------------------------
# 2016-10-30  sudodus  created dus-live from mkusb-nox
# 2016 11-14  sudodus  dus-live version 0.0.0
# 2016-12-29  sudodus  version 12.0.0 - mkusb-dus
# 2017-03-29  sudodus  improved logic for running and reporting gpt_fix
# 2017-03-29  sudodus  version 12.0.8
# 2017-05-05  sudodus  ${source/.iso} --> ${source%.iso}   # fixes for some
#                      ${source/.img} --> ${source%.img}   # unusual file names
#                      ${source/.img.[gx]z} --> ${source%.img.[gx]z}
# 2017-05-05  sudodus  version 12.1.4
# 2017-09-21  sudodus  dus-live: function partition_msdos_fat: extracting
#                      from the file 'grub4win.img.xz' to clone the head
#                      and the partition with grub for BIOS mode when
#                      running in an installed system in UEFI mode
# 2017-09-21  sudodus  version 12.2.8
# 2019-11-16  sudodus  modifications for nvme drives (alongside mmcblk)
# 2019-11-16  sudodus  version 12.3.8
# 2020-05-30  sudodus  added p_zentest, wf_prep, wf_cleanup to use watch-flush
# 2020-05-30  sudodus  version 12.5.7
# 2020-09-06  sudodus  mkcmd_runcmd: size also when cloning from block device
# 2020-09-06  sudodus  version 12.5.9
# 2020-09-21  sudodus  gpt_fix: added "-e 'Problem:'" to first grep command
# 2020-09-21  sudodus  version 12.6.6
# 2021-01-22  sudodus  mkcmd_runcmd:
#                      ... wait for the buffered data to get flushed ...
# 2021-01-22  sudodus  version 12.6.8
# 2021-11-17  sudodus  quoted grep 'patterns'
# 2021-11-17  sudodus  version 12.7.2

version="${0##*/} 12.7.2"

bs=4096
curlang="$LANG"
curdir="$(pwd)"
#LC_ALL=C
#LANG=C
ans=
pff=
startdir="$PWD"
inversvid="\0033[7m"
resetvid="\0033[0m"
faintvid="\0033[2m"
redback="\0033[1;37;41m"
greenback="\0033[1;37;42m"
blueback="\0033[1;37;44m"
disk_name_type=
distr=$(grep -i '^ID=' /etc/*release|sed s/.*ID=//)
source=
target=
grubimg=false
result=
mkusb_sdir="/usr/share/mkusb"
mkdir -p "$mkusb_sdir"
biosbl=true
size=
manager=

########################################################################

function read_pff {

# reading $1
# assigning common variable(s) (declared above)

if [ "${1:0:4}" == "pff:" ]
then
# cat "${1/pff:}"
 for i in source target
 do
  read $i
 done < "${1/pff:}"
 rm     "${1/pff:}"
 echo "source=$source"
 echo "target=$target"
# echo "persistent=$persistent"  # persistent is a dummy variable here
else
 echo "no pff input"
fi
}
########################################################################

function sed_mtab {

if [ "$distr" == "mageia" ]  # keep track of mageia's live drive
then
 return
fi

sync
for i in $(grep '^/dev/[^f]d' /etc/mtab|tr -s ' ' ' '|cut -d ' ' -f 1)
do
 match=false
 for j in $(df 2>/dev/null|grep '/dev/[^f]d'|tr -s ' ' ' '|cut -d ' ' -f 1)
 do
  if [ "$i" == "$j" ]
  then
   match=true
#   echo "$i matches"
  fi
 done
 if ! "$match"
 then
#  echo sed -i "\%^$i%D" /etc/mtab
  sed -i "\%^$i%D" /etc/mtab
 fi
done
#cat /etc/mtab
}
########################################################################

function win_check {

iso=$(mktemp -d --tmpdir dus.XXXXXXXXXX)
#echo "iso=$iso"
#echo "$source"

if [ "${source%.iso}.iso" == "$source" ]
then
 echo "The iso file SHOULD BE loop mounted on a temporary file READ-ONLY:"
 sleep 0.5
 umount "$iso" >/dev/null 2>&1
 modprobe loop  # for debian jessie
 sync
 mount -o loop -t auto "$source" "$iso"
 
 disk_name_type=""

 ( test -f "$iso"/bootmgr || test -f "$iso"/bootmgr.efi ) && test -f "$iso"/setup.exe 
 if [ $? -eq 0 ]
 then
  disk_name_type=$(find "$iso" -iname "*microsoft-windows*"|head -n1)
  if [ "$disk_name_type" != "" ]
  then
    disk_name_type="microsoft-windows"
  fi
 fi
 umount "$iso"
 rmdir "$iso"
fi

if [ "${source/.tar}.tar" == "$source" ]
then
 tar -tvf "$source" | grep -m1 'microsoft-windows' > /dev/null
 if [ $? -eq 0 ]
 then
  disk_name_type="microsoft-windows"
 fi
fi

if [ "$disk_name_type" == "microsoft-windows" ]
then
 echo "disk_name_type=$disk_name_type"
fi
}
########################################################################

function win_install {

# variables

LANG=C

ruler='-------20%-------40%-------60%-------80%------100% progress'

if [ "$distr" == "debian" ]
then
 insmd1=
 insmd2=
else
 insmd1="insmod ntfs
#   insmod msdos
   insmod part_msdos
   insmod search_label"
 insmd2="insmod ntfs
   insmod chain
   insmod part_msdos
   insmod part_gpt"
fi
grub_win_install="default=0
timeout=15

menuentry \"Install Windows in BIOS mode alias CSM (no such grub menu in UEFI mode)\" {
    $insmd1
    search --no-floppy --set=root --label WIN-INSTALL --hint hd0,msdos1
    ntldr /bootmgr
    boot
}

menuentry \"Boot from the first hard drive\" {
    $insmd2
    set root=(hd1)
    chainloader +1
    boot
}"

# managing tarfile (intermediate file)

echo "source=$source"
if [ "${source/.tar}.tar" == "$source" ]
then
 echo "tar"
 tarfil="$source"
else
 echo "iso"
 tarfil="${source/.iso}.tar"
fi
#echo "tarfil=$tarfil"
result=
swapoff "$target"* 2>/dev/null
sync
doing_this="Installing Windows to $target ... :"
gpt_zap "$target"

# creating partition table and file system

partition_msdos_fat
part_info "$target"

# creating temporary directories to mount source file and target directory

tsrc=$(mktemp -d --tmpdir dus.XXXXXXXXXX)
tprt=$(mktemp -d --tmpdir dus.XXXXXXXXXX)
#echo "tsrc=$tsrc"
#echo "tprt=$tprt"
#  pwd
#  echo "$source"
#  echo "$tarfil"

# extracting content from iso file to tarfile

if test -f "$tarfil"
then
 echo "Using the mkusb tarfile
$tarfil

It is convenient to keep both the isofile and tarfile. Remove one of them
afterwards if you want to save space:
- keep the tarfile to create a USB boot drive
- keep the isofile to create a DVD boot disk (or create another tarfile)"
else
 fresiz=$(df -m .|tail -n1|tr -s ' ' ' '|cut -d ' ' -f4)
 if [ $fresiz -lt 5120 ]
 then
echo "--------------------------------------------------------------------------"
  LANG=C df -h |grep -e '^File' -e '/dev/'
  read -p "
--------------------------------------------------------------------------
Not enough space for a tarfile to be written where the iso file is stored.
Enter a directory in a partition/drive with > 5 GiB free: " tardir
 else
  tardir="$curdir"
 fi
 srctmp=${source##*/}
 tarfil="$tardir"/"${srctmp/.iso}.tar"
 ssize="$(wc -c "$source")"
 ssize="${ssize%% *}"
 rstep=$(( $ssize/500000 ))
 mount -o loop "$source" "$tsrc"
 cd "$tsrc"
 echo "Creating an intermediate mkusb tarfile for Windows:
- keep the tarfile to create a USB boot drive
- keep the isofile to create a DVD boot disk (or create another tarfile)"
 echo -e "$inversvid Extracting from iso-file to tarfile (a few minutes) ... $resetvid"
 echo "$ruler"
 tar --checkpoint=."$rstep" --hard-dereference -chf "$tarfil" . \
  2> "$curdir/mkusb-tar.log"                                      # tar #####
 if [ $? -ne 0 ]; then result="$result 'tar isofile-to-tarfile':error";fi
 echo "   finished"
 cd "$curdir"
 umount "$tsrc"
fi

# extracting from tarfile to target device

if [ "${target:0:11}" == "/dev/mmcblk" ] || [ "${target:0:9}" == "/dev/nvme" ]
then
  mount "${target}p1" "$tprt"
else
  mount "${target}1" "$tprt"
fi
#  ls -l "${target}1"
#  ls -ld "$tprt"
sync
sleep 1.0
echo -e "$inversvid Extracting from tarfile to target device (several minutes) ... $resetvid"
ssize="$(wc -c "$tarfil")"
ssize="${ssize%% *}"
rstep=$(( $ssize/500000 ))

if test -f "$tarfil"
then
 echo "using '$tarfil'"
elif test -f "$curdir/$tarfil"
then
 echo "using '$curdir/$tarfil'"
else
 echo "error: could not find '$tarfil'"
fi
#echo "tprt=$tprt"
#echo "pwd"
#pwd

echo "$ruler"
tar --checkpoint=."$rstep" --no-same-owner --no-same-permissions \
 --hard-dereference --directory "$tprt" -xhf "$tarfil" 2>> "$curdir/mkusb-tar.log"      # tar #####
if [ $? -ne 0 ]; then result="$result 'tar tarfile-to-target':error";fi
echo "   finished"
cd "$curdir"
if test -s "$curdir/mkusb-tar.log"
then
 read -p "Check errors logged by tar? (y/N) " ans
 if [ "$ans" == "y" ]
 then
  more "$curdir/mkusb-tar.log"
 fi
 echo -e "This method is verified with Windows 7 - 10.
There are errors when using some iso files. 
$inversvid The target device might work anyway. Please try! $resetvid"
else
 rm "$curdir/mkusb-tar.log"
fi

##     rsync -rLtD --info=progress2 "$tsrc"/ "$tprt"
#      rsync -rLtD --info=progress2 /mnt/sd2/ "$tprt"  # read from partition ***** works *****
#
# rsync and cp fail to copy the directory tree with files recursively from loop mount

sleep 1.0
sync
sleep 1.0

# installing bootloader from BIOS mode

if $biosbl
then
 if [ "$distr" == "opensuse" ]
 then
  which grub2-install > /dev/null
 else
  which grub-install > /dev/null
 fi
 if [ "$?" != "0" ]
 then
  echo "Please install grub-pc if you want to boot Windows in BIOS mode"
 else
  echo -n "Bootloader: "
  if [ "$distr" == "opensuse" ]
  then
   mkdir -p "$tprt"/boot/grub2/
   grub2-install --force --target=i386-pc --boot-directory="$tprt/boot" "$target"
  else
   mkdir -p "$tprt"/boot/grub/
   grub-install --force --target=i386-pc --boot-directory="$tprt/boot" "$target"
  fi
  if [ $? -ne 0 ]; then result="$result grub-install:error"; fi
  sync
  if [ "$distr" == "opensuse" ]
  then
   echo "$grub_win_install" > "$tprt"/boot/grub2/grub.cfg
  else
   echo "$grub_win_install" > "$tprt"/boot/grub/grub.cfg
  fi
  if [ $? -ne 0 ]; then result="$result grub.cfg :error"; fi
  sync
 fi
elif ! $grubimg
then
 /bin/echo -e "Cannot install grub for BIOS mode from an installed system in UEFI mode.
$inversvid The created system should work in UEFI mode, $resetvid
if the ISO file is made for UEFI mode (Windows 8-10 64-bit).
If you use 'grub4win.img.xz', it should work in BIOS mode too."
fi

# finishing
 
umount "$tprt"
if [ $? -ne 0 ]; then result="$result umount:error"; fi
sleep 1.0
sync
rmdir "$tsrc" "$tprt"
if [ $? -ne 0 ]; then result="$result rmdir:error"; fi
if [ "$result" == "" ]
then
 echo -e "$greenback Done :-) $resetvid"
else
 echo -e "$redback mkcmd_runcmd: $result. Failed. $resetvid"
fi
}
########################################################################

function mkcmd_runcmd {

# make command and run command, 'here we go'

LANG=C

# installing linux distros and cloning from images and devices

swapoff "$target"* 2>/dev/null
sync
gpt_zap "$target"
doing_this="Installing '$source' to '$target' ... :"

# write 'a first line' to the terminal ...

echo "
$doing_this
"
  
# build beginning of command (read the source) and calculate size

if [ "${source%.iso}" != "$source" ] || [ "${source%.img}" != "$source" ]
then
 readsrc="< \"$source\""  # extra quotes to work with some special characters
 size=$(wc -c "$source"|cut -d ' ' -f 1)
 psiz="-s ${size,,}"
elif [ "${source%.img.[gx]z}" != "$source" ]
then
 if [ "${source%.img.gz}.img.gz" == "$source" ]
 then
  readsrc="zcat \"$source\" |"  # extra quotes to work with some special characters
  size=$(gzip -l "$source"|grep "${source/.gz}"|tr -s ' ' ' '|sed s/^\ //|cut -d ' ' -f 2)
 else
  readsrc="xzcat \"$source\" |"  # extra quotes to work with some special characters
  size=$(xz --robot --list "$source" | tail -n1 | cut -f5)
 fi
 psiz="-s ${size,,}"
else
 readsrc="< \"$source\""  # extra quotes to work with some special characters
 if test -b "$source"
 then
  size=$(lsblk -ndbo size "$source")
  psiz="-s ${size,,}"
 else
  psiz=
 fi
fi

# build pvpipe (if available)

if which pv
then
 pvpipe="pv $psiz |"
else
 pvpipe=
fi
#  echo "\$1=$1"
#  echo "source=$source"
#  echo "target=$target"
#  echo "bs=$bs"
#  echo "size=$size"
#  echo "pvpipe=$pvpipe"
#  echo "readsrc=$readsrc"

cmdfile=$(mktemp --tmpdir dus.XXXXXXXXXX)
#echo 'cmdfile=$cmdfile'

cmdline="$readsrc $pvpipe dd bs=$bs $cnt of=$target"

echo "$cmdline"|tee $cmdfile
echo -e "$inversvid Please wait for sync until 'Done' is written.$resetvid
$blueback If there is a progress window,$resetvid
$blueback wait for the buffered data to get flushed $resetvid
$blueback so that all data are transferred to the target device.$resetvid"
# echo 'cat $cmdfile'
# cat $cmdfile

p_zentest
if [ "$manager" == "z" ] && which watch-flush
then
 wf=true
else
 wf=false
fi
if $wf
then
 wf_prep
fi

bash $cmdfile
if [ $? -eq 0 ]
then
 if [ "${source%.iso}.iso" != "$source" ]
 then
  gpt_fix "$target"
 fi
 result="$greenback Done :-) $resetvid"
else
 result="$redback Failed :-( $resetvid"
fi
echo "Syncing the device ..."
rm $cmdfile

if $wf
then
 wf_cleanup
else
 sync
fi
echo -e "$result"

LANG="$curlang"
}
########################################################################

function mk_msdos {

# make an MSDOS partition table and a FAT32 file system

success=true
target="$1"
label1="$2"
if [ "$label1" == "" ]
then
 read -p "Enter label for the partition (max 11 *standard* ascii characters) " label1
fi
label1="${label1:0:11}"
label1="${label1^^}"
#echo "Label (name) for the FAT32 partition: $label1"

echo "Trying to unmount partitions if mounted on the target device"
umount "$target"*
df | grep "$target"
if [ $? -eq 0 ]
then
 echo "mk_msdos: could not unmount a partition on the target device"
 exit
fi

echo "------------------------------------------------------------"
dd if=/dev/zero of="$target" bs=1024 count=1024 2>&1
sleep 0.5
parted -s "$target" mklabel msdos
sleep 0.5
if [ "$disk_name_type" == "microsoft-windows" ]
then
 seker=$(sudo parted -ms "$target" unit s print|grep "$target"|cut -d : -f 2|sed 's/s//')
 buser=$(sudo parted -ms "$target" unit s print|grep "$target"|cut -d : -f 5)
# echo "seker=$seker ; buser=$buser"
 if [ "$seker" != "" ] && [ "$buser" != "" ]
 then
  cnter=$(( 1024*1024 / $buser ))
  echo dd if=/dev/zero of="${target}" bs=$buser count=$cnter seek=$(($cnter))
       dd if=/dev/zero of="${target}" bs=$buser count=$cnter seek=$(($cnter))
  echo dd if=/dev/zero of="${target}" bs=$buser count=$cnter seek=$(($seker -$cnter))
       dd if=/dev/zero of="${target}" bs=$buser count=$cnter seek=$(($seker -$cnter))
  sync
 else
  success=false
  echo "Failed to find sectors and/or units for wiping the end of target device"
 fi
fi
sleep 0.5
parted -s "$target" mkpart primary 1048576b 100%
sleep 0.5
parted -s "$target" set 1 boot on  # set boot flag on partition 1
parted -s "$target" set 1 esp on   # set boot flag on partition 1
sleep 0.5
if [ "${target:0:11}" == "/dev/mmcblk" ] || [ "${target:0:9}" == "/dev/nvme" ]
then
 mkfs.vfat -v -F 32 -n "$label1" "${target}p1"
else
 mkfs.vfat -v -F 32 -n "$label1" "${target}1"
fi
if [ $? -ne 0 ]
then
 success=false
fi
sleep 0.5
sync
sudo blkid -c /dev/null "${target}"* # > /dev/null 2>&1
sleep 0.5

if $success
then
 /bin/echo -e "$inversvid created MSDOS partition table and FAT file system $resetvid"
else
 /bin/echo -e "$inversvid mk_msdos: could not create MSDOS partition table and FAT file system $resetvid"
 return 1
fi
}
########################################################################

function partition_msdos_fat {

if test -d /sys/firmware/efi
then
 rdev=$(df | grep -m1 '/$'|cut -d ' ' -f1)
 if ! ( [ "$rdev" == "/cow" ] || [ "$rdev" == "aufs" ] || \
    [ "$rdev" == "rootfs" ] || [ "$rdev" == "overlay" ] )
 then
  biosbl=false
  echo "$separator"
  message="${version} cannot install 'grub-pc' in installed systems in UEFI mode.
'grub-pc' is used to make persistent live drives bootable in BIOS mode.

Instead you can use 'grub4win.img.xz', an image with the grub content.

$inversvid Minimum 8 GB:$resetvid You need a drive (USB pendrive or memory card) with
at least 8 GB because the image is expanded to 7.744 GB (to allow for
undersized 8 GB drives)."
  /bin/echo -en "$message"
  echo ""
  ans=
  /bin/echo -en "$blueback Do you want to use 'grub4win.img.xz'? (y/N) $resetvid"
   read ans
  if [ "$ans" == "y" ]
  then
   grubimg=true
   if ! test -f "$mkusb_sdir"/grub4win.img.xz
   then
    echo "grub4win.img.xz: not found" \
"The image file 'grub4win.img.xz' is not found.
Please install the package 'usb-pack-efi'"
    exit
   fi
  fi
 fi
fi

#grubimg=true  ############################### testing only

if $grubimg
then
 echo "pv \"$mkusb_sdir\"/grub4win.img.xz | xzcat -c | dd of=\"$target\" bs=4096"
 echo "Cloning the head of the drive and the partition including grub.
Please wait for sync (flushing the buffers) ..."
 if which pv
 then
  pv "$mkusb_sdir"/grub4win.img.xz | xzcat -c | dd of="$target" bs=4096
 else
  <  "$mkusb_sdir"/grub4win.img.xz   xzcat -c | dd of="$target" bs=4096
 fi
 sync
 echo "target=$target"
else
 mk_msdos "$target" WIN-INSTALL
 if [ $? -ne 0 ]; then result="$result mk_msdos:error"; fi
fi
partprobe
}
########################################################################

function part_info {

target=$1
sync
sleep 0.5
if [ "${target:0:11}" == "/dev/mmcblk" ]
then
 read -p "Unplug and re-plug the flash card to see the correct info ... and press Enter "
#elif [ "$disk_name_type" == "microsoft-windows" ]
#then
# read -p "Unplug and re-plug the target drive to see the correct info ... and press Enter "
fi
blkid -c /dev/null "${target}?" > /dev/null
sleep 0.5
partinfo=$(parted -s "$target" print; \
echo " "; \
lsblk -o MODEL,NAME,FSTYPE,LABEL "$target")

echo "$partinfo"
}
########################################################################

function gpt_fix {

# $1 is the target device

echo \
"v
q" \
| gdisk "$1" 2>/dev/null |grep -e 'GPT: damaged' -e 'Problem:' > /dev/null 2>&1
if [ $? -eq 0 ]
then
 echo \
"v
x
e
r
d
w
y" \
| gdisk "$1" > /dev/null 2>&1

 echo \
"v
q" \
| gdisk "$1" 2>/dev/null |grep -e 'GPT: damaged' -e 'Problem:' > /dev/null 2>&1
 if [ $? -eq 0 ]
 then
  echo "gpt_fix: failed to fix the GUID partition table (GPT) of $1"
 else
  echo "gpt_fix: done :-)"
 fi
else
 echo "gpt_fix: checked :-)"
fi
}
########################################################################

function gpt_zap {

# $1 is the target device

echo \
"
x
z
y
y" \
| gdisk "$1" > /dev/null 2>&1

echo "gpt_zap: done"
}
#######################################################################

function p_zentest {

zenity --info --title="$version - zenity-test" --timeout 1 \
 --width=350 --height=150 \
--text="Checking if zenity works in this environment" > /dev/null 2>&1
exitnr=$?
if [ $exitnr -eq 0 ] || [ $exitnr -eq 5 ]
then
 manager=z
else
 return 1
fi
}
########################################################################

function wf_prep {

tailfile=$(mktemp)
if [ "$manager" == "z" ]
then
 ( watch-flush "$size" "$tailfile" > /dev/null ) & pid0=$!

 ( tail -f "$tailfile"| zenity --progress --title="$version - progress ..." \
 --width=500 --height=400 \
 --percentage=0 --auto-close --no-cancel \
 --window-icon="/usr/share/icons/hicolor/48x48/apps/mkusb.png"  2>> "/dev/null") & pid1=$!
else
 watch-flush "$size" "$tailfile" & pid0=$!
fi
}
########################################################################

function wf_cleanup {

echo -en "$faintvid"
if [ "$manager" != "z" ]
then
 echo ""
fi
echo "----- cleanup after writing ------------------------------------------"
sync
echo "100
# buffered data : 0 kB -- watching -- rate : 0 -- eta : n.a." >> "$tailfile"
sleep 5.5
ps -A|grep "^ *$pid0"
if [ $? -eq 0 ]
then
 kill "$pid0"
fi
if [ "$manager" == "z" ]
then
 ps -A|grep "^ *$pid1"
 if [ $? -eq 0 ]
 then
  kill "$pid1"
 fi
fi
rm  "$tailfile"
sleep 2
partprobe
sleep 4
umount "$target"*
echo -en "$resetvid"
}
########################################################################
#
# main
#
########################################################################

read_pff "$1"

echo "source=$source
ls -l  $source"
ls -l "$source"

if [ "$source" == "" ] && [ "$target" == "" ]
then
 echo "No source and no target"
 exit
elif [ "$source" == "" ]
then
 echo "No source"
 exit
elif [ "$target" == "" ]
then
 echo "No target"
 exit
fi

if test -s "$source" && test -b "$target"
then
 if [ "${source%.iso}.iso" == "$source" ]
 then
  echo "Making a USB boot drive or memory card .........................."
 elif [ "${source%.img}.img" == "$source" ] \
   || [ "${source%.img.gz}.img.gz" == "$source" ] \
   || [ "${source%.img.xz}.img.xz" == "$source" ]
 then
  echo "Cloning to a USB drive or memory card ..........................."
 elif [ "${source/.tar}.tar" == "$source" ]
 then
  tar -tvf "$source" | grep -m1 'microsoft-windows' > /dev/null
  if [ $? -eq 0 ]
  then
   disk_name_type="microsoft-windows"
   echo "Making a USB boot device or memory card with Windows ..........."
  else
   echo "Bad choice -- try again"
   exit
  fi
 else
  echo "Bad choice -- try again"
  exit
 fi
elif test -b "$source" && test -b "$target"
then
 echo "Cloning a device to a USB drive or memory card ..................."
else
  echo "Bad choice -- try again"
  exit
fi

# make command and run command

win_check
if [ "$disk_name_type" == "microsoft-windows" ] \
|| [ "${source/.tar}.tar" == "$source" ]
then
 win_install        # windows iso files and tar files
else
 mkcmd_runcmd       # most other iso files and [compressed] image files
fi
sed_mtab
cd "$startdir"
