#!/bin/bash
#update to the latest release.
#suggest to run this: sakura -h -c 80 -r 30 -t "EasyUpdate" -e /usr/local/easy_version/easy-update
#called from /usr/sbin/easy-update, no parameters.
#200729 first release.
#200730 only have de, fr builds online. some fixes.

export TEXTDOMAIN=easy-update
export OUTPUT_CHARSET=UTF-8

if [ -t 0 ];then
 true #we are running this from a terminal, good.
else
 exit 13
fi
PARENT="${$}"

. /etc/rc.d/PUPSTATE #has PUP_HOME
. /etc/DISTRO_SPECS #has DISTRO_BINARY_COMPAT, DISTRO_COMPAT_VERSION DISTRO_TARGETARCH
. /root/.packages/DISTRO_PET_REPOS #has PET_REPOS, PACKAGELISTS_PET_ORDER, SFS_REPOS

mkdir -p /tmp/easy_version
MSGexit="$(gettext 'Script terminated, close the window')"

echo -e '\033[1;35m' #1;35 foreground bright magenta
#echo "EasyUpdate"
echo "$(gettext 'Welcome. this script will download the latest release of EasyOS and automatically update the current installation.')" | fold -s -w ${COLUMNS}
echo "$(gettext 'It uses the rsync utility to download only the differences between the current version and the latest online easy-*.img.gz file, which is much smaller and faster than downloading the entire file.')" | fold -s -w ${COLUMNS}
echo "$(gettext 'The script will place the new vmlinuz, initrd and easy.sfs files into the boot-partition and auomatically fix initrd, then all you will need to do is reboot and you have updated.')" | fold -s -w ${COLUMNS}
echo "$(gettext 'If you have an Internet connection and want to test if there is a new release and download it, continue with the script...')" | fold -s -w ${COLUMNS}
echo -e '\033[1;34m' #1;34 foreground bright blue
echo -n "$(gettext 'Press ENTER to continue (any other character then ENTER to quit):') "
read goforit
echo -e '\033[0;39m' #reset foreground to default
[ "$goforit" != "" ] && echo -e "\033[1;31m${MSGexit}\033[0;39m" && exit 0

#find Master Boot Record...
MBRBIN=""
[ -f /usr/lib/syslinux/mbr.bin ] && SLPATH="/usr/lib/syslinux"
[ "$SLPATH" = "" ] && [ -f /usr/lib/SYSLINUX/mbr.bin ] && SLPATH="/usr/lib/SYSLINUX" #141102 ubuntu utopic unicorn.
[ "$SLPATH" = "" ] && [ -f /usr/share/syslinux/mbr.bin ] && SLPATH="/usr/share/syslinux"
[ "$SLPATH" ] && MBRBIN="${SLPATH}/mbr.bin"
#170129 ubuntu 16.04 xenial xerus devs have really gone to town moving stuff around...
[ ! "$MBRBIN" ] && [ -f /usr/lib/syslinux/mbr/mbr.bin ] && MBRBIN='/usr/lib/syslinux/mbr/mbr.bin'
echo
if [ ! "$MBRBIN" ];then
 echo -en '\033[1;31m' #bright red.
 echo "$(gettext 'Sorry, cannot find file mbr.bin. Looked in /usr/lib/syslinux,
/usr/lib/syslinux/mbr, /usr/lib/SYSLINUX and /usr/share/syslinux. You have an
abnormal installation of Syslinux. Aborting')"
 echo -e '\033[0;39m' #reset.
 echo -e "\033[1;31m${MSGexit}\033[0;39m"
 exit 4
fi

#find out if a later release online, only at ibiblio.org...
echo -en '\033[1;35m' #magenta
echo -n "$(gettext 'Probing ibiblio.org to see if there is a later release...')"
echo -e '\033[0;39m' #reset.
[ -f /tmp/easy_version/buster ] && rm -f /tmp/easy_version/buster
wget -4 -t 2 -T 20 --waitretry=20 --directory-prefix=/tmp/easy_version --level=1 http://distro.ibiblio.org/easyos/${DISTRO_TARGETARCH}/releases/${DISTRO_COMPAT_VERSION}
#...this creates a html file /tmp/easy_version/buster
if [ ! -s /tmp/easy_version/buster ];then
 echo -en '\033[1;31m' #bright red.
 echo "$(gettext 'Sorry, there was an error probing ibiblio.org, aborting script.')"
 echo -e '\033[0;39m' #reset.
 echo -e "\033[1;31m${MSGexit}\033[0;39m"
 exit 1
fi
#LATESTVER="$(grep -o 'href="[^"]*' /tmp/easy_version/buster | tail -n 1 | cut -f 2 -d '"' | cut -f 1 -d '/')"
VERS="$(grep -o 'href="[^"]*' /tmp/easy_version/buster | cut -f 2 -d '"' | cut -f 1 -d '/')"
sortedVERS="$(echo "$VERS" | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n)" #lowest to highest. or, could use full sort "-V" option.
latestVER="$(echo "$sortedVERS" | tail -n 1)"
if [ "$latestVER" == "" ];then
 echo -en '\033[1;31m' #bright red.
 echo "$(gettext 'Sorry, there was an error probing ibiblio.org, aborting script.')"
 echo -e '\033[0;39m' #reset.
 echo -e "\033[1;31m${MSGexit}\033[0;39m"
 exit 2
fi

vercmp ${DISTRO_VERSION} lt ${latestVER}
if [ $? -ne 0 ];then #=0 if true.
 echo -en '\033[1;31m' #bright red.
 echo "$(gettext 'The latest online version is:') ${latestVER}"
 echo "$(gettext 'The current installed version is:') ${DISTRO_VERSION}"
 echo "$(gettext 'No later version online, so exiting script.')"
 echo -e '\033[0;39m' #reset.
 echo -e "\033[1;31m${MSGexit}\033[0;39m"
 exit 3
else
 echo -en '\033[1;34m' #bright blue
 echo "$(gettext 'The latest online version is:') ${latestVER}"
 echo "$(gettext 'The current installed version is:') ${DISTRO_VERSION}"
 echo "$(gettext 'Newer online version, so downloading...')"
 echo -e '\033[0;39m' #reset.
fi

#ask for a download location, must have 2GB free space...
BLOCKbytes="$(stat -f -c %S /mnt/${WKG_DEV})" #block size, usually 4096
FREEblocks="$(stat -f -c %f /mnt/${WKG_DEV})"
FREEk=$(expr ${FREEblocks} \/ 1024 \* ${BLOCKbytes})
FREEm=$(expr ${FREEk} \/ 1024)
if [ $FREEm -lt 2000 ];then
 echo -en '\033[1;31m' #bright red.
 echo "$(gettext 'Sorry, /mnt/wkg must have at least 2GB free space. Aborting')"
 echo -e '\033[0;39m' #reset.
 echo -e "\033[1;31m${MSGexit}\033[0;39m"
 exit 7
else
 echo -en '\033[1;32m' #bright green.
 echo "$(gettext 'Good. Required free space in /mnt/wkg is 2GB, you have:') ${FREEm}MB"
 echo -en '\033[0;39m' #reset.
fi
DL_PATH="/mnt/${WKG_DEV}/${WKG_DIR}" #same as /mnt/wkg
cd $DL_PATH

#ask if have a .img.gz of current version...
LANGinsert='' #200730 only have de, fr builds online...
[ "${LANG:0:2}" == "de" ] && LANGinsert="-de"
[ "${LANG:0:2}" == "fr" ] && LANGinsert="-fr"
echo
echo -en '\033[1;35m' #bright magenta
echo "$(gettext 'The rsync utility will compare the easy*.img.gz of the current version with that of the new version, and only download the differences. This will be much less than downloading the entire new .img.gz file.')" | fold -s -w ${COLUMNS}
echo "$(gettext 'You do not need the easy*.img.gz current version, as this script will reconstruct it.')" | fold -s -w ${COLUMNS}

rm -f easy-*.img 2>/dev/null
rm -f easy-*.img.gz 2>/dev/null

echo
echo -en '\033[1;34m' #bright blue
echo "$(gettext 'However, if you do have this file somewhere:')"
echo "easy-${DISTRO_VERSION}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz"
echo "$(gettext 'Then it will not have to be reconstructed.')"
echo "$(gettext 'If you do have it, copy it to here, immediately:') ${DL_PATH}"
echo "$(gettext 'Do it now, then press the ENTER key.')"
echo "$(gettext 'If you have not got it, just press the ENTER key and it will be reconstructed.')" | fold -s -w ${COLUMNS}
echo -n "$(gettext 'When ready, press ENTER key:') "
read keepgoing

if [ -f easy-${DISTRO_VERSION}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz ];then
 sync
 mv -f easy-${DISTRO_VERSION}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz
else
 #echo -e '\033[1;34m' #bright blue
 #echo -n "Press ENTER to reconstruct easy-${DISTRO_VERSION}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz (CTRL-C to quit): " | fold -s -w ${COLUMNS}
 #echo -en '\033[0;39m' #reset.
 #read goagain
 #[ "$goagain" != "" ] && exit 8
 
 #create a pseudo-file .img.gz of the current release... (code from 2createpcskeletonimage in woofq)
 echo
 echo -en '\033[1;35m' #bright magenta
 echo "$(gettext 'Reconstructing') easy-${DISTRO_VERSION}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz ..."
 echo "$(gettext 'Creating a 1281MB blank image file...')"
 echo -en '\033[0;39m' #reset.
 #note, slightly bigger than 1280MB...
 dd if=/dev/zero of=easy-CURRENT.img bs=1M count=1281 status=progress conv=fsync oflag=sync
 sync
 echo -en '\033[1;35m' #bright magenta
 echo "$(gettext 'Creating a new dos partition table, using fdisk...')"
 echo -en '\033[0;39m' #reset.
 echo -e 'o\nw\n' | fdisk easy-CURRENT.img
 sync
 echo -en '\033[1;35m' #bright magenta
 echo "$(gettext 'Writing Master Boot Record...')"
 echo -en '\033[0;39m' #reset.
 dd bs=440 conv=notrunc count=1 if=${MBRBIN} of=easy-CURRENT.img
 sync
 #create 639MB partition, so total size of image will be 640MB (and a 2nd partition will start on a 8MB boundary)
 echo -en '\033[1;35m' #bright magenta
 echo "$(gettext 'Creating 639MB fat32 esp partition...')"
 echo -en '\033[0;39m' #reset.
 echo -e 'n\np\n1\n2048\n+639M\nw\n' | fdisk easy-CURRENT.img
 sync
 #set partition-id to efi...
 echo -e 't\nef\nw' | fdisk easy-CURRENT.img
 sync
 #set the boot flag...
 echo -e 'a\nw' | fdisk easy-CURRENT.img
 sync
 echo "$(gettext 'Creating fat32 filesystem...')"
 LOOPDEV="$(losetup -f)"
 LOOPDEV=${LOOPDEV##*/}
 losetup -o 1048576 /dev/${LOOPDEV} easy-CURRENT.img #part starts 1M
 [ $? -ne 0 ] && echo -e "\033[1;31m${MSGexit}\033[0;39m" && exit 5
 mkdosfs -F 32 -n easy1 /dev/${LOOPDEV} #FAT32.
 sync
 #install files into esp, only has to be roughly similar...
 mkdir -p /mnt/${LOOPDEV} #ex: /mnt/loop2
 mount -t vfat /dev/${LOOPDEV} /mnt/${LOOPDEV}
 [ $? -ne 0 ] && echo -e "\033[1;31m${MSGexit}\033[0;39m" && exit 6
 echo -e '\033[1;35m' #bright magenta
 echo "$(gettext 'Populating fat32 esp partition...')"
 echo -en '\033[0;39m' #reset.
 cp -a /mnt/wkg/releases/easy-${DISTRO_VERSION}/initrd /mnt/${LOOPDEV}/
 sync
 cp -a /mnt/wkg/releases/easy-${DISTRO_VERSION}/vmlinuz /mnt/${LOOPDEV}/
 sync
 cp -p -L /mnt/wkg/releases/easy-${DISTRO_VERSION}/easy.sfs /mnt/${LOOPDEV}/easy.sfs
 sync
 umount /mnt/${LOOPDEV}
 losetup -d /dev/${LOOPDEV} 2>/dev/null
 sleep 0.5 #seem to need delay for loop device to become free.
 losetup -a >/dev/null
 echo -en '\033[1;35m' #bright magenta
 echo "$(gettext 'Creating 640MB ext4 partition...')"
 echo -en '\033[0;39m' #reset.
 echo -e "n\np\n2\n\n+655360K\nw" | fdisk -u easy-CURRENT.img
 sync
 echo "$(gettext 'Creating ext4 f.s. with journal, encrypt...')"
 losetup -o 671088640 /dev/${LOOPDEV} easy-CURRENT.img #part starts 640M
 mke2fs -t ext4 -O encrypt,has_journal,^64bit,^uninit_bg -L easy2 -m 0 -b 4096 /dev/${LOOPDEV}
 sync
 losetup -d /dev/${LOOPDEV}
 
 echo -en '\033[1;35m' #bright magenta
 echo "$(gettext 'Compressing') easy-${DISTRO_VERSION}${LANGinsert}-${DISTRO_TARGETARCH}.img ..."
 echo -en '\033[0;39m' #reset.
 #however, giving it same name as the latest .img file...
 mv -f easy-CURRENT.img easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img
 gzip --rsyncable easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img
 sync
fi

#use rsync to download latest...
echo
echo -en '\033[1;35m' #bright magenta
echo "$(gettext 'Downloading') easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz ..."
echo -en '\033[0;39m' #reset.
#-t preserve modification times, -v verbosity, -c checksum compare
#rsync -tvc distro.ibiblio.org::easyos/amd64/releases/buster/${latestVER}/easy-${latestVER}-${DISTRO_TARGETARCH}.img.gz ./easy-${latestVER}-${DISTRO_TARGETARCH}.img.gz
#...get a "protocol error", this works...
if [ "${LANGinsert}" == "" ];then #200730
 rsync -av distro.ibiblio.org::easyos/amd64/releases/buster/${latestVER}/easy-${latestVER}-${DISTRO_TARGETARCH}.img.gz ./easy-${latestVER}-${DISTRO_TARGETARCH}.img.gz
 RETVAL=$?
else
 rsync -av distro.ibiblio.org::easyos/amd64/releases/buster/${latestVER}/${LANG:0:2}/easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz ./easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz
 RETVAL=$?
fi
if [ $RETVAL -ne 0 ];then
 echo -en '\033[1;31m' #bright red.
 echo "$(gettext 'Something went wrong with the download. Aborting')"
 echo -en '\033[0;39m' #reset.
 rm -f easy-*.img.gz 2>/dev/null
 rm -rf ./.cache 2>/dev/null
 echo -e "\033[1;31m${MSGexit}\033[0;39m"
 exit 9
fi

#offer to install...
echo -en '\033[1;35m' #bright magenta
echo "$(gettext 'This file has been downloaded:')"
echo "/mnt/${WKG_DEV}/${WKG_DIR}easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz"
echo "$(gettext 'You may do a manual update, by clicking on the file to uncompress it, click again to open it up, drag vmlinuz, initrd and easy.sfs to the boot-partition, then click on initrd to fix the BOOT_SPECS file. These steps are documented online.')" | fold -s -w ${COLUMNS}
echo "$(gettext 'However, this script can do it automatically. Make your choice...')"
echo -en '\033[0;39m' #reset.
echo -e '\033[1;34m' #bright blue
echo -n "$(gettext 'Press ENTER for automatic update (any other key to quit):') "
echo -en '\033[0;39m' #reset.
read autoupdate
[ "$autoupdate" != "" ] && echo -e "\033[1;31m${MSGexit}\033[0;39m" && exit 10

#update boot-partition...
echo
echo -en '\033[1;35m' #bright magenta
echo "$(gettext 'Extracting files vmlinuz, initrd and easy.sfs...')"
echo -en '\033[0;39m' #reset.
gunzip easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz
sync
mkdir -p mntpt
mount -t vfat -o loop,offset=1048576 easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img mntpt #start sector=2048, = 2048x512 bytes
if [ $? -ne 0 ];then
 echo -en '\033[1;31m' #bright red.
 echo "$(gettext 'Something is wrong with the downloaded file. Deleting it and aborting.')"
 echo -en '\033[0;39m' #reset.
 umount mntpt 2>/dev/null
 rm -f easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img
 echo -e "\033[1;31m${MSGexit}\033[0;39m"
 exit 11
fi
BOOTflg=0
grep -q '^/dev/${BOOT_DEV} ' /proc/mounts
if [ $? -ne 0 ];then
 mkdir -p /mnt/${BOOT_DEV}
 mount -t vfat /dev/${BOOT_DEV} /mnt/${BOOT_DEV} #200730 fix.
 BOOTflg=1
fi

echo -en '\033[1;35m' #bright magenta
echo "$(gettext 'Extracting BOOT_SPECS file from initrd, current installation...')"
echo -en '\033[0;39m' #reset.
[ -d initrd-tree ] && rm -rf initrd-tree #200730 just in case.
mkdir initrd-tree
cd initrd-tree
cat /mnt/${BOOT_DEV}/${BOOT_DIR}initrd | cpio -i -d -m
sync
cp -f BOOT_SPECS ../
cd ..
sync
rm -rf initrd-tree

echo -en '\033[1;35m' #bright magenta
echo "$(gettext 'Copying new vmlinuz, initrd and easy.sfs to boot-partition...')"
echo -en '\033[0;39m' #reset.
cp -a -f mntpt/vmlinuz /mnt/${BOOT_DEV}/${BOOT_DIR}
sync
cp -a -f mntpt/initrd /mnt/${BOOT_DEV}/${BOOT_DIR}
sync
cp -a -f mntpt/easy.sfs /mnt/${BOOT_DEV}/${BOOT_DIR}
if [ $? -ne 0 ];then
 echo -en '\033[1;31m' #bright red.
 echo "$(gettext 'Copy failed. Aborting.')"
 echo "$(gettext 'Downloaded file still there, if you want to try manual install.')"
 echo -en '\033[0;39m' #reset.
 sync
 umount mntpt
 echo -e "\033[1;31m${MSGexit}\033[0;39m"
 exit 12
fi
sync
umount mntpt
rmdir mntpt #200730 fix.

echo -en '\033[1;35m' #bright magenta
echo "$(gettext 'Recompressing the downloaded .img file to .img.gz ...')"
echo -en '\033[0;39m' #reset.
gzip --rsyncable easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img
sync

#fix initrd...
echo -en '\033[1;35m' #bright magenta
echo "$(gettext 'Inserting BOOT_SPECS file into new initrd...')"
echo -en '\033[0;39m' #reset.
mkdir -p initrd-tree
cd initrd-tree
cat /mnt/${BOOT_DEV}/${BOOT_DIR}initrd | cpio -i -d -m
sync
mv -f ../BOOT_SPECS ./
#update initrd...
rm -f /mnt/${BOOT_DEV}/${BOOT_DIR}initrd
sync
find . | cpio -o -H newc > /mnt/${BOOT_DEV}/${BOOT_DIR}initrd
sync
cd ..
rm -rf initrd-tree

#maybe unmount boot-partition...
[ $BOOTflg -eq 1 ] && umount /mnt/${BOOT_DEV}

echo
echo -en '\033[1;32m' #bright green.
echo "$(gettext 'Finished!')"
echo "$(gettext 'This is the boot-partition:') ${BOOT_DEV}"
if [ "$BOOT_DIR" ];then
 echo "$(gettext 'Which has this folder:') /${BOOT_DIR}"
fi
echo "$(gettext 'Which has the new files vmlinuz, initrd and easy.sfs')"
echo "$(gettext 'The new version will be:') ${latestVER}"
echo "$(gettext 'All that you have to do is reboot!')"
echo -en '\033[0;39m' #reset.

echo
echo -en '\033[1;34m' #blue
echo "$(gettext 'This is the downloaded file:')"
echo "/mnt/${WKG_DEV}/${WKG_DIR}easy-${latestVER}${LANGinsert}-${DISTRO_TARGETARCH}.img.gz"
echo "$(gettext 'It is not needed anymore. You can delete it or archive it somewhere.')"
echo "$(gettext 'If you want to archive it, move it somewhere else, or it will get deleted next time this script is run.')" | fold -s -w ${COLUMNS}
echo
#echo -n "Script finished, press ENTER to exit: "
echo -en '\033[0;39m' #reset.
echo -e "\033[1;31m${MSGexit}\033[0;39m"
#read wearedone

###end###
