#!/bin/bash

#    Ikki_USB_Creator_fat32.sh - Créer une clé USB bootable avec une partition FAT32 depuis un fichier iso
#    Copyright (C) 2007-2024  Julien Billard

#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.

#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.

#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <https://www.gnu.org/licenses/>.

# https://ikkiboot.tuxfamily.org
# Version: 1.0 - 30/12/2023

export LANG=C
set -e
label_fat32="IKKIBOOT"
script=$0
mount_ikki=/media/mount_ikki
mount_usb=/media/mount_usb

# Aide
usage() {
cat <<EOF

Usage: $0 -i [Iso] -L [Label]
Options:
  -i	Nom du fichier ISO
  -L	Nom de la clé, par défaut ${label_fat32}
  -t	Nom du périphérique de destination (Expert)
  -D	Mode debug
  -h	Affiche ce message
	
Exemples:
  $0 -i Ikki_Boot.iso
  $0 -i Ikki_Boot.iso -L Job
  $0 -i Ikki_Boot.iso -t /dev/sdX
  $0 -i Ikki_Boot.iso -L Job -t /dev/sdX
	
EOF
}

# Gestion des options
while getopts ":i:L:s:t:Dh" option; do
    case "${option}" in
        i)
			iso=${OPTARG}
			;;
		L)
			label_fat32=${OPTARG}
			;;
		t)
			target=${OPTARG}
			;;
		h|*)
			usage
			exit 1
			;;
    esac
done

# Vérifie si l'utilisateur est root
if [[ "${UID}" -ne 0 ]]; then
	echo
	echo "[${LOGNAME}] Vous devez exécuter ce script en tant que root."
	echo
	exit 1
fi

# Vérifie si la commande fdisk fonctionne
if ! [[ -x "$(command -v fdisk)" ]]; then
        echo
        echo "Vous devez vous connecter en root avec la commande :"
        echo "su -"
        echo
        exit 1
fi

# Vérifie si un paramètre a été utilisé
if [[ $# -eq 0 ]]; then 
	usage
	exit 1
fi

# Vérifie si l'option -i a été utilisée
if [[ -z "${iso}" ]]; then
	usage
	exit 1
fi

# Vérifie le nombre de caractère du label
if [ "${#label_fat32}" -gt 11 ]; then 
	echo
	echo "Le nom de la première partition de la clé ne doit pas dépasser 11 caractères" 
	echo
	exit 1
fi

# Test si le fichier est un .iso
len=${#iso}
len=$((len-3))
if [[ "${iso:len}" != "iso" ]]; then
	usage
	exit 1
fi

# Vérifie si le fichier ISO existe
if [[ ! -f "${iso}" ]]; then
	echo
    echo "Le fichier ${iso} n'existe pas";
	echo
    exit 1
fi

# Vérifie si le fichier ISO est dans le même répertoire que le script
if [[ $(dirname "${iso}") != $(dirname "${script}") ]]; then
	echo
	echo "Le fichier ISO doit être dans le même répertoire que ce script"
	echo
    exit 1
fi

if [[ -z "${target}" ]]; then
	{
		# Liste les périphériques amovible de type disque
		list_key=$(lsblk -nbdpo NAME,SIZE,TYPE,HOTPLUG | grep -Ev " 0.disk" | grep -E ".disk.*1$")
	} || {
		echo
		echo "Aucune clé USB n'a été détecté"
		echo
		exit 1
	}

	# Nombre de disque amovible détecté
	nbr_word=$(echo "${list_key}" | wc -w)
	nbr_key=$((nbr_word / 4))

	if [[ "${nbr_key}" -eq 1 ]]; then
		target=$(echo "${list_key}" | awk '{print $1}')
		target_space=$(echo "${list_key}" | awk '{print $2}')
		echo
		echo "Une clé USB a été détectée :"

		lsblk -dpo MODEL,NAME,SIZE | grep -E "${target}"
		echo
		while [[ "${confirmation}" != "o" ]] && [[ "${confirmation}" != "n" ]] ; do
			read -rp "Confirmez-vous l'utilisation de cette clé o/n ? " confirmation
		done
	elif [[ "${nbr_key}" -gt 1 ]]; then
		echo
		echo "Plusieurs clés USB ont été détectées :"
		echo
		lsblk -dpo MODEL,NAME,SIZE,TYPE,HOTPLUG | grep -Ev " 0.?.disk" | grep -E ".disk.*1$" | rev | cut -d ' ' -f3- | rev | sed s/disk//g
		echo
		echo "Une seule clé USB doit être branchée"
		echo
		exit 1
	fi
	
else
	# Test $target
	{
		list_key=$(lsblk -nbdpo NAME,SIZE,TYPE,HOTPLUG | grep -E "${target}.*disk.*1$")
	} || {
		echo
		echo "Le périphérique de destination ${target} n'est pas amovible"
		echo
		exit 1
	}
	echo
	echo "Périphérique de destination :"
	lsblk -dpo MODEL,NAME,SIZE | grep -E "${target}"
	target_space=$(echo "${list_key}" | awk '{print $2}')
	echo
	while [[ "${confirmation}" != "o" ]] && [[ "${confirmation}" != "n" ]] ; do
		read -rp "Confirmez-vous l'utilisation de cette clé o/n ? " confirmation
	done
	
fi

if [[ "${confirmation}" = "n" ]]; then
	exit 1
fi

# Vérifie si la clé est en cours d'utilisation si c'est le cas on la démonte
target_use=$(mount | grep "${target}" | awk '{print $3}')
if [[ -n "${target_use}" ]]; then
	echo
	echo "La clé USB est actuellement utilisée et va être démontée"
	set +e
	for use in ${target_use}; do umount "${use}";done
	set -e
fi

# Si la clé est toujours en cours d'utilisation on quitte
target_use=$(mount | grep "${target}" | awk '{print $3}')
if [[ -n "${target_use}" ]]; then
	echo
	echo "La clé USB est toujours utilisée :"
	echo "${target_use}"
	echo
	echo "Quittez toutes les applications qui utilisent cette clé et réessayez"
	echo
	exit 1
fi

iso_space=$(du -b "${iso}" | awk '{print $1}')

# Vérifie la taille de la clé par rapport au fichier ISO
if [[ "${iso_space}" -gt "${target_space}" ]]; then
	echo
	echo "Une clé d'une plus grande capacité est nécessaire pour ce fichier ISO"
	echo
	exit 1
fi

# On copie le contenu de l'image ISO sur la clé USB
target_space=$((target_space/1024/1024/1024))

while [[ "${confirmation}" != "OUI" ]] && [[ "${confirmation}" != "NON" ]] ; do
	echo
	read -rp "Etes-vous sûr de vouloir effacer le disque ${target} de ${target_space} Go (OUI/NON) : " confirmation
done
if [[ "${confirmation}" == "OUI" ]] ; then
	echo
	
	# Création de la partition FAT32
	echo "1) Création de la partition"
	(
	echo o                  # create a new empty MBR (DOS) partition table
	echo n                  # Add a new partition
	echo p                  # Primary partition
	echo 1			        # Partition number
	echo                    # First sector (Accept default)
	echo                    # Last sector (Accept default)
	echo t 			        # Type
	echo 0c                 # FAT32
	sleep 5 || true
	echo w                  # Write changes
	echo q                  # Quit
	) | fdisk -w always "${target}"
	
	until fdisk -l | grep "${target}"1 1> /dev/null
	do
	  sleep 1
	done
	
	# Formatage de la partition en FAT32
	label_fat32=$(echo "${label_fat32}" | tr "[:lower:]" "[:upper:]")
	mkfs.vfat -F 32 -n "${label_fat32}" "${target}1"
	
    echo
	echo "2) Copie du contenu de l'image ISO sur la clé"
	echo
	if [[ ! -d "${mount_ikki}" ]]; then
		mkdir -p "${mount_ikki}"
		to_delete_iso=true
	fi
	mount -o loop "${iso}" "${mount_ikki}" >/dev/null 2>&1
	
	if [[ ! -d "${mount_usb}" ]]; then
		mkdir -p "${mount_usb}"
		to_delete_usb=true
	fi
	mount -t vfat "${target}1" "${mount_usb}"
	
	# Affiche l'avancement de la copie
	#for file in "${mount_ikki}"/*; do echo Copie "${file}"; cp -rfL "${file}" "${mount_usb}";sync;done
	find "${mount_ikki}" -mindepth 1 -maxdepth 1 \! -type l -exec bash -c 'echo Copie $(basename "$1")' shell {} \; -exec cp -rf "{}" "${mount_usb}" \; -exec sync \;
	echo
	echo "Copie terminée"
	
	umount "${mount_ikki}"
	
	echo
	echo "3) Installation de Syslinux"
	cp -a "${mount_usb}"/script/syslinux/linux /tmp
	cd /tmp/linux
	
	# Installe Syslinux
	chmod +x extlinux
	./extlinux -i "${mount_usb}"/boot/syslinux/
	
	# Copie le MBR de Syslinux
	dd conv=notrunc bs=440 count=1 if=mbr.bin of="${target}"
	
	# Ajoute le drapeau boot
	sfdisk -A "${target}" 1 >/dev/null 2>&1
	
	sync
	umount "${mount_usb}"
	
	# Nettoyage
	if [[ "${to_delete_usb}" = true ]]; then
		rm -rf "${mount_usb}"
	fi
	
	if [[ "${to_delete_iso}" = true ]]; then
		rm -rf "${mount_ikki}"
	fi
	
	rm -rf /tmp/linux
	
else
	exit 1
fi

sync

echo
echo "La clé USB a été créé avec succès"
echo

