#!/bin/bash
clear

C_RED_BLD='\033[1;31m' C_YLW_BLD='\033[1;93m' C_GRN_BLD='\033[1;32m' C_BLU_BLD='\033[1;94m' C_CYN_BLD='\033[1;36m' C_WHT_BLD='\033[1;37m' C_GRY_BLD='\033[1;30m'
C_RED='\033[0;91m'	  C_YLW='\033[0;93m'		 C_GRN='\033[0;92m'		C_BLU='\033[0;94m'	  C_CYN='\033[0;36m'		 C_WHT='\033[0;37m'		C_GRY='\033[0;30m'
C_BLANK='\033[0m'      C_FLASH='\033[1;5m'

TOOLKIT_PATH="$(pwd)" # "${HOME}/ps4"

BACKUP_PATH="${TOOLKIT_PATH}/backup" # default one, can be overwritten later
BACKUP_TYPE_USR="User Data"
BACKUP_TYPE_SET="Settings"
BACKUP_TYPE_SCR="Screenshots"
BACKUP_TYPE_VID="Videos"
BACKUP_TYPE_MED="All Multimedia"

function function_apps_1() {
	echo -e "${C_YLW_BLD}CP${C_BLANK} variant have disabled backup path write permissions checking, free space and"
	echo -e "total size checking. Overwriting existed files is also disabled. Its usage is"
	echo -e "intended only for damaged yet still mountable UFS2."
	echo
	echo -e "${C_YLW_BLD}RSYNC${C_BLANK} variant, syncing data between source and target path. Shouldn't be used"
	echo -e "if disk came from PS4 with dead RTC."
	echo
	echo -e " ${C_WHT_BLD}A.${C_BLANK} cp"
	echo -e " ${C_WHT_BLD}B.${C_BLANK} rsync"
	echo
	}

function function_apps_2() {
	echo -e "${C_YLW_BLD}CP${C_BLANK} variant have disabled backup path write permissions checking, free space and"
	echo -e "total size checking. Overwriting existed files is also disabled. Its usage is"
	echo -e "intended only for damaged yet still mountable UFS2."
	echo
	echo -e "${C_YLW_BLD}RSYNC${C_BLANK} variant, syncing data between source and target path. Shouldn't be used"
	echo -e "if disk came from PS4 with dead RTC."
	echo
	echo -e " ${C_WHT_BLD}A.${C_BLANK} cp (all files)"
	echo -e " ${C_WHT_BLD}B.${C_BLANK} cp (media filtered)"
	echo -e " ${C_WHT_BLD}C.${C_BLANK} rsync"
	echo
	}

function function_paths_checks() {
	sudo -v
	if [[ ! -w ${BACKUP_PATH} ]]; then
		echo
		echo -e "${C_RED_BLD}ERROR!${C_RED} Backup destination is ${C_RED_BLD}NOT${C_RED} writable by current user."
		read -p "Press any key to exit script. "
		exit
	fi
	echo
	SIZE_TAKEN=$(sudo du -b -h -l -s "${TOOLKIT_PATH}/storage/hdd/user" | cut -f1)
	SIZE_FREE=$(sudo df -h --output=avail ${BACKUP_PATH} | grep -e K -e M -e G -e T -e P | tr -d \ )
	if [[ "$(ls -A "${TOOLKIT_PATH}/storage/hdd/user")" ]]; then
		echo      -e "${C_WHT_BLD}Total${C_BLANK} space occupied on user partition:   ${C_WHT_BLD}${SIZE_TAKEN}iB${C_BLANK}"
		else echo -e "${C_WHT_BLD}Total${C_BLANK} space occupied on user partition:   ${C_RED_BLD}NOT mounted!${C_BLANK}"
	fi
	echo -e "${C_WHT_BLD}Free${C_BLANK} space available in backup path on PC: ${C_WHT_BLD}${SIZE_FREE}iB${C_BLANK}"
	echo
	read -p "Press any key to continue. "
	echo
	}

function function_exit() {
	echo -e "${C_RED}"
	read -p "Write one of the options... Press enter key to exit script. "
	exit
	}

# ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

echo -e "${C_GRN_BLD}PS4 HDD Backuper v1.3 by Berion"
echo -e "${C_YLW}Script for making a backup of important data."
echo
echo -e "${C_RED}Partitions ${C_RED_BLD}must be${C_RED} already mounted (can be Read Only)."
echo -e "Confirm root permissions every time you will be asked for."
echo

# ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

echo -e "${C_CYN_BLD}STEP 1: Backup Destination${C_BLANK}"
echo
echo -e "${C_WHT_BLD}Choose where to save data from PS4 disk:${C_BLANK}"
echo -e " ${C_WHT_BLD}1.${C_BLANK} User defined backup path:    ${C_YLW}<?>${C_BLANK}"
echo -e " ${C_WHT_BLD}2.${C_BLANK} Default path:                ${C_YLW}${BACKUP_PATH}/${C_BLANK}"
echo -e " ${C_WHT_BLD}3.${C_BLANK} Linux temporary data:        ${C_YLW}/tmp/${C_BLANK}"
echo -e " ${C_WHT_BLD}4.${C_BLANK} RAM disk:                    ${C_YLW}/mnt/ramdisk/${C_BLANK}"
echo -e " ${C_WHT_BLD}5.${C_BLANK} Windows 11 system partition: ${C_YLW}/media/OS/${C_BLANK}"
echo
while :; do
read MENU_1
case $MENU_1 in
	1)
		if [[ ! -e "${TOOLKIT_PATH}/configurations" ]]; then mkdir "${TOOLKIT_PATH}/configurations"; fi
		if [[ -f "${TOOLKIT_PATH}/configurations/backup_path.txt" ]]; then
			echo
			echo -e "Found configuration file with custom path:"
			echo -e "${C_YLW}$(cat "${TOOLKIT_PATH}/configurations/backup_path.txt")${C_BLANK}"
			BACKUP_PATH="$(cat "${TOOLKIT_PATH}/configurations/backup_path.txt")"
			echo
			if [[ ! -s "${TOOLKIT_PATH}/configurations/backup_path.txt" ]]; then
				echo -e "${C_RED_BLD}ERROR:${C_RED} Configuration file is empty..."
				read -p "Press enter key to exit script. "
				rm "${TOOLKIT_PATH}/configurations/backup_path.txt"
				exit
			fi
			if [[ $(grep -c '^$' "${TOOLKIT_PATH}/configurations/backup_path.txt") -eq 1 ]] && [[ $(wc -l < "${TOOLKIT_PATH}/configurations/backup_path.txt") -eq 1 ]]; then
				echo -e "${C_RED_BLD}ERROR:${C_RED} Configuration file is empty..."
				read -p "Press enter key to exit script. "
				rm "${TOOLKIT_PATH}/configurations/backup_path.txt"
				exit
			fi
			if [[ ! -e ${BACKUP_PATH} ]]; then
				echo -e "${C_RED_BLD}ERROR:${C_RED} Above path does NOT exist or is NOT mounted!"
				read -p "Press enter key to exit script. "
				exit
			fi
			else
				echo
				echo -e "Type direct path to backup folder i.e \"${C_YLW}/media/OS/Users/JohnDoe/Desktop${C_BLANK}\"."
				echo -e "${C_RED}Do NOT use ${C_RED_BLD}white space${C_RED}, ${C_RED_BLD}slash${C_RED} at the end of path and ${C_RED_BLD}quotation marks${C_RED}.${C_BLANK}"
				echo
				read BACKUP_PATH
				echo
				echo -e "Ok, so you've chosen: \"${C_YLW_BLD}${BACKUP_PATH}${C_BLANK}\"."
				echo
				if [[ ! -e ${BACKUP_PATH} ]]; then
					echo -e "${C_RED_BLD}ERROR:${C_RED} \"${BACKUP_PATH}\" does NOT exist or is NOT mounted!"
					read -p "Press enter key to exit script. "
					exit
				fi
				echo "${BACKUP_PATH}" >> "${TOOLKIT_PATH}/configurations/backup_path.txt"
		fi
		break;;

	2)
		BACKUP_PATH="${TOOLKIT_PATH}/backup"
		echo
		break;;

	3)
		BACKUP_PATH="/tmp"
		echo
		break;;

	4)
		if [[ -e "/mnt/ramdisk" ]]; then
			BACKUP_PATH="/mnt/ramdisk"
			echo
			else
				echo
				echo -e "${C_RED_BLD}ERROR!${C_RED} RAM disk does NOT exist!${C_RED}"
				read -p "Press any key to exit script. "
				exit
		fi
		break;;

	5)
		if [[ -e "/media/OS" ]]; then
			BACKUP_PATH="/media/OS"
			echo
			else
				echo
				echo -e "${C_RED_BLD}ERROR!${C_RED} Windows 11 system partition not mounted or has different label."
				read -p "Press enter key to exit script. "
				exit
		fi
		if [[ -f "${BACKUP_PATH}/hiberfil.sys" ]]; then
			echo
			echo -e "${C_RED_BLD}Warning!${C_RED} Windows Fast Boot is turned ON."
			read -p "Press enter key to exit script, preventing damage of NTFS partition. "
			exit
			else sleep 0
		fi
		break;;

	*)
		function_exit
		break;;
esac
done

# ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

echo -e "${C_CYN_BLD}STEP 2: Backup Type${C_BLANK}"
echo
echo -e "${C_WHT_BLD}Choose what you want to copy:${C_BLANK}"
echo -e " ${C_WHT_BLD}1.${C_BLANK} Saves, Trophies and Licenses (encrypted per console)."
echo -e " ${C_WHT_BLD}2.${C_BLANK} Settings and Account Data (encrypted per console)."
echo -e " ${C_WHT_BLD}3.${C_BLANK} Screenshots and Videos."
echo

while :; do
read MENU_2
echo
case $MENU_2 in
	1)
		# /user/license/*												    licenses
		# /home/savedata/*											[?] purpose unknown
		# /user/trophy/conf/<NPWR ID>/*							    global trophy sets
		# /home/<ffffffff>/trophy/data/<NPWR ID>/*			    user trophy sets
		# /home/<ffffffff>/trophy/data/sce_trop/*				    user trophy sets index
		# /home/<ffffffff>/trophy/db/trophy_local.db			    cached SEN trophy list
		# /home/<ffffffff>/savedata/<GAME ID>/*				    PS4 games and emulators saves
		# /home/<ffffffff>/savedata/sce_backup/*				[?] purpose unknown
		# /home/<ffffffff>/savedata/sce_backup2/*				[?] purpose unknown
		# /home/<ffffffff>/savedata_meta/user/<GAME ID>/*	    icons etc. and *.sfo
		# /home/<ffffffff>/license/rev2							[?] purpose unknown
		# /home/<ffffffff>/username.dat							    user name in PS4DM

		function_apps_1
		while :; do
		read MENU_SUB
		echo
		case $MENU_SUB in
			A | a)
				sudo -v && echo
				sudo mkdir -p "${BACKUP_PATH}/${BACKUP_TYPE_USR}" &> /dev/null
				sudo cp -r --update=none "${TOOLKIT_PATH}/storage/hdd/user/home"     "${BACKUP_PATH}/${BACKUP_TYPE_USR}/"
				sudo cp -r --update=none "${TOOLKIT_PATH}/storage/hdd/user/license"  "${BACKUP_PATH}/${BACKUP_TYPE_USR}/"
				sudo cp -r --update=none "${TOOLKIT_PATH}/storage/hdd/user/savedata" "${BACKUP_PATH}/${BACKUP_TYPE_USR}/"
				sudo cp -r --update=none "${TOOLKIT_PATH}/storage/hdd/user/trophy"   "${BACKUP_PATH}/${BACKUP_TYPE_USR}/"
				break;;

			B | b)
				function_paths_checks
				sudo mkdir -p "${BACKUP_PATH}/${BACKUP_TYPE_USR}" &> /dev/null
				sudo rsync -am --info=progress2 --include={'*/','license/***'}                      --exclude='*' ${TOOLKIT_PATH}/storage/hdd/user/ "${BACKUP_PATH}/${BACKUP_TYPE_USR}/"
				sudo rsync -am --info=progress2 --include={'*/','trophy/***'}                       --exclude='*' ${TOOLKIT_PATH}/storage/hdd/user/ "${BACKUP_PATH}/${BACKUP_TYPE_USR}/"
				sudo rsync -am --info=progress2 --include={'*/','savedata/***','savedata_meta/***'} --exclude='*' ${TOOLKIT_PATH}/storage/hdd/user/ "${BACKUP_PATH}/${BACKUP_TYPE_USR}/"
				break;;

			*)
				function_exit
				break;;
		esac
		done
		break;;

	2)
		# /user/settings/system.eap
		# /system_data/settings/system.dat
		# /system_data/settings/system.idx
		# /system_data/settings/system.nvs
		# /system_data/settings/system.rec

		function_apps_1
		while :; do
		read MENU_SUB
		echo
		case $MENU_SUB in
			A | a)
				sudo -v && echo
				sudo mkdir -p "${BACKUP_PATH}/${BACKUP_TYPE_SET}" &> /dev/null
				sudo cp --update=none "${TOOLKIT_PATH}/storage/hdd/user/settings/system.eap" "${BACKUP_PATH}/${BACKUP_TYPE_SET}/"
				if [[ "$(ls -A "${TOOLKIT_PATH}/storage/hdd/system_data")" ]]; then
					sudo cp --update=none "${TOOLKIT_PATH}/storage/hdd/system_data/settings/." "${BACKUP_PATH}/${BACKUP_TYPE_SET}/"
					else echo -e "\n${C_RED_BLD}WARNING:${C_RED} \"system_data\" partition NOT mounted. Settings copied only partially.${C_BLANK}"
				fi
				break;;

			B | b)
				function_paths_checks
				sudo mkdir -p "${BACKUP_PATH}/${BACKUP_TYPE_SET}" &> /dev/null
				sudo rsync -a --info=progress2 "${TOOLKIT_PATH}/storage/hdd/user/settings/system.eap"	"${BACKUP_PATH}/${BACKUP_TYPE_SET}/"
				if [[ "$(ls -A "${TOOLKIT_PATH}/storage/hdd/system_data")" ]]; then
					sudo rsync -a --info=progress2 "${TOOLKIT_PATH}/storage/hdd/system_data/settings/"	"${BACKUP_PATH}/${BACKUP_TYPE_SET}/"
					else echo -e "\n${C_RED_BLD}WARNING:${C_RED} \"system_data\" partition NOT mounted. Settings copied only partially.${C_BLANK}"
				fi
				break;;

			*)
				function_exit
				break;;
		esac
		done
		break;;

	3)
	 # /user/av_contents/content_tmp/*.mp4
	 # /user/av_contents/photo/NPXS20001/CUSA03450/<fff>/*.png or *.jpg
	 # /user/av_contents/video/NPXS20103/CUSA01433/<fff>/*.mp4

		function_apps_2
		while :; do
		read MENU_SUB
		echo
		case $MENU_SUB in
			A | a)
				sudo -v && echo
				sudo mkdir -p "${BACKUP_PATH}/${BACKUP_TYPE_MED}" &> /dev/null
				sudo cp -r --update=none "${TOOLKIT_PATH}/storage/hdd/user/av_contents/." "${BACKUP_PATH}/${BACKUP_TYPE_MED}/"
				break;;

			B | b)
				sudo -v && echo
				sudo mkdir -p "${BACKUP_PATH}/${BACKUP_TYPE_SCR}" &> /dev/null
				sudo mkdir -p "${BACKUP_PATH}/${BACKUP_TYPE_VID}" &> /dev/null
				cd "${TOOLKIT_PATH}/storage/hdd/user/av_contents" &> /dev/null
				sudo find . -name '*.jpg' -not -path "*/thumbnails/*" -print0 | xargs -0 sudo cp -t "${BACKUP_PATH}/${BACKUP_TYPE_SCR}/" &> /dev/null
				sudo find . -name '*.png' -not -path "*/thumbnails/*" -print0 | xargs -0 sudo cp -t "${BACKUP_PATH}/${BACKUP_TYPE_SCR}/" &> /dev/null
				sudo find . -name '*.mp4' -print0 | xargs -0 sudo cp -t                             "${BACKUP_PATH}/${BACKUP_TYPE_VID}/" &> /dev/null
				break;;

			C | c)
				function_paths_checks
				sudo mkdir -p "${BACKUP_PATH}/${BACKUP_TYPE_MED}" &> /dev/null
				sudo rsync -amr --info=progress2 --include={'*/','*.jpg','*.png'} --exclude='*' "${TOOLKIT_PATH}/storage/hdd/user/av_contents/" "${BACKUP_PATH}/${BACKUP_TYPE_MED}/"
				sudo rsync -amr --info=progress2 --include={'*/','*.mp4'} --exclude='*'         "${TOOLKIT_PATH}/storage/hdd/user/av_contents/" "${BACKUP_PATH}/${BACKUP_TYPE_MED}/"
				break;;

			*)
				function_exit
				break;;
		esac
		done
		break;;

	*)
		function_exit
		break;;
esac
done

sudo chown -R $(id -nu):$(id -ng) "${BACKUP_PATH}/"
find ${BACKUP_PATH} -type d -exec chmod 755 {} \;
find ${BACKUP_PATH} -type f -exec chmod 644 {} \;

# ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

unset BACKUP_PATH
unset BACKUP_TYPE_USR
unset BACKUP_TYPE_MED
unset BACKUP_TYPE_SET
unset BACKUP_TYPE_SCR
unset BACKUP_TYPE_VID
unset MENU_1
unset MENU_2
unset MENU_SUB
unset SIZE_FREE
unset SIZE_TAKEN

echo -e ${C_WHT_BLD}
read -p "All done. Press enter key to exit. "
