#!/bin/sh
#(c) Copyright Barry Kauler December 2013, bkhome.org
#Licence GPL3 (refer: /usr/share/doc/legal).
#131219 installs quirky 6.x to a hard drive partition.
#131227 no longer put image-file into target.
#131231 vfat is ok as working partition.
#140108 version sort.
#140120 work in new quirky build system.
#140123 if installed to a removable drive, the grub "root=/dev/$TARGETPART" is not adequate.
#140212 install .sfs of deployed .usfs.xz, to /audit/reference
#140213 record date of creation of reference .sfs
#140213 merged install-quirky-to-partition.sh into 4install-quirky-to-partition
#141021 code was in wrong place.
#150109 check that 'sort' supports --version-sort option.
#150129 bump minimum recommended size from 2GB to 8GB.
#150225 mksquashfs use only 1 core.
#150727 no longer writing .sfs to /audit/reference
#151213 no longer hardcode DEV1FS. see also /sbin/initNEW, /etc/rc.d/rc.sysinit, /usr/local/install_quirky/install-quirky-to-*
#160424 set INSTALLED_MODE=full in /etc/rc.d/install.log

if [ -d rootfs-skeleton -a -f 3builddistro ];then #140213
 #running in quirky build system.
 if [ ! -d sandbox3 ];then
  echo "You need to run 3builddistro first, to build sandbox3/*.usfs.xz"
  exit
 fi
. ./DISTRO_SPECS
 RUNNING="build"
 cd sandbox3
else
 RUNNING="user"
fi


echo
echo "This script will install Quirky to a partition on a hard drive."
echo "Any kind of hard drive is acceptable, including conventional magnetic
platter or SSD (Solid State Disk -- Flash media).
Removable drives, such as USB drives, are also acceptable.
The partition must ALREADY have a filesystem. For normal magnetic media,
ext2, ext3, or ext4 is recommended. For SSD, f2fs is recommended."
echo "The partition will need to be at least 8GB in size, and all of the
partition will be erased (install a Service Pack PET to upgrade an earlier
installation of Quirky, not this script)."
echo "If you do not have a suitable available partition, abort this script!"
echo
echo "The script will ask questions at each step, and will offer a choice of
partitions to install to, but of course it comes down to you to make an
intelligent choice and not erase a partition with important files on it!"
echo "This script should work when running any Linux distribution, however, it
works best when running a Puppy Linux or Puppy Linux-derivative, as Puppy has,
in my opinion, many superior utilities. However, this script will check for
existence or otherwise of those utilities and downgrade appropriately, or
abort if a missing utility is essential."
echo
echo -n "Press ENTER key to continue (CTRL-C to abort): "
read goforit

###check sanity###
if [ "`whoami`" != "root" ];then
 echo
 echo "Sorry, you need to run this script as root (administrator). Aborting."
 exit
fi
if [ $1 ];then
 echo
 echo "Nothing required on commandline, this script will ask."
fi
for AUTILITY in blkid cp dd ls mount sed sort stat xz
do
 if [ "`which ${AUTILITY}`" = "" ];then
  echo
  echo "Sorry, the '${AUTILITY}' utility is missing. Aborting."
  exit
 fi
done
#150109 check that 'sort' supports --version-sort option:
echo -e '2\n1' | sort --version-sort > /dev/null 2>&1
if [ $? -ne 0 ];then
 echo
 echo "Sorry, the version of 'sort' utility is too old.
It needs to support the '--version-sort' option.
Upgrade package 'coreutils', or upgrade your distro. Aborting."
 exit
fi

IMGLIST="$(ls -1 ./ | grep '\.usfs\.xz$' | sort --key=2 --field-separator='-' --version-sort)" #140108 version sort. 140213
if [ "$IMGLIST" = "" ];then
 echo "The Quirky compressed image file should have been downloaded"
 echo "to the same folder in which you are running this script."
 echo "It will be named something like '*.usfs.xz'"
 echo "Please download it from distro.ibiblio.org/quirky/quirky6/x86"
 exit
fi
#need linux f.s.... 131231 no, vfat is ok...
touch tempfile1 #140213 no, create a file.
WKGFS="$(stat -f tempfile1 | grep -o 'Type: .*' | grep -E 'ext2|ext3|ext4|reiserfs|f2fs')"
rm -f tempfile1
#if [ "$WKGFS" = "" ];then
# echo
# echo "Sorry, but you must be running this script in a partition with a Linux
#filesystem. The 'stat' utility was used to check for ext2, ext3, ext4, reiserfs
#or f2fs filesystem, however some versions of stat do not recognise f2fs.
#If you are running in a f2fs filesystem, or some other Linux filesystem
#(but definitely NOT a ntfs, msdos or vfat f.s.!!!), then press any printable
#character on the keyboard, then ENTER key, to continue."
# echo -n "To abort, press ENTER key only: "
# read tostop
# [ "$tostop" = "" ] && exit
#fi

###choose .usfs.xz file###
echo
CNT=1
echo -n "" > /tmp/quirkyimgs
for AIMG in `echo -n "$IMGLIST" | tr '\n' ' '`
do
 echo "${CNT} ${AIMG}" >> /tmp/quirkyimgs
 CNT=`expr $CNT + 1`
done
cat /tmp/quirkyimgs
echo
echo -n "Type number of image file: "
read numimg
[ "$numimg" = "" ] && exit
IMGFILEXZ="$(cat /tmp/quirkyimgs | head -n ${numimg} | tail -n 1 | cut -f 2 -d ' ')"
echo "...ok, have chosen ${IMGFILEXZ}"
if [ ! -f $IMGFILEXZ ];then
 echo "sorry, file ${IMGFILEXZ} does not exist"
 exit
fi
EXT="$(echo -n $IMGFILEXZ | rev | cut -f 1 -d '.' | rev)"
if [ "$EXT" != "xz" ];then
 echo "sorry, file ${IMGFILEXZ} is not xz-compressed"
 exit
fi
echo
echo "Testing integrity of compressed file, please wait..."
xz --test $IMGFILEXZ
if [ $? -ne 0 ];then
 echo
 echo "Sorry, file appears to be corrupted. Try downloading again."
 exit
fi

if [ "$RUNNING" = "build" ];then #140213 running in quirky build system.
 FILEPREFIX="$DISTRO_FILE_PREFIX"
else
 FILEPREFIX="$(echo -n "$IMGFILEXZ" | cut -f 1 -d '-')" #140130
fi

#expand img file...
echo
IMGFILE="$(basename ${IMGFILEXZ} .xz)"
echo "Uncompressing ${IMGFILEXZ} to ${IMGFILE}..."
rm -f ${IMGFILE} 2>/dev/null
xz --decompress --stdout ${IMGFILEXZ} > ${IMGFILE}
sync
echo '...done'

####choose target partition###
ALLPARTS="$(cat /proc/partitions | grep -o -E 'sd[a-z][0-9]|sd[a-z][0-9][0-9]|hd[a-z][0-9]|sd[a-z][0-9][0-9]|mmcblk0p[0-9]|mmcblk0p[0-9][0-9]' | tr '\n' ' ')"
echo
echo "These are all the partitions:"
echo "$ALLPARTS"
if which probedisk > /dev/null 2>&1;then
 echo
 echo "These are all the drives:"
 probedisk
fi
if which probepart > /dev/null 2>&1;then
 echo
 echo "These are all of the partitions, showing sizes in MB:"
 probepart -m | grep -v 'none'
fi
echo
echo "You will need to choose one of these to install Quirky to. It must have a
Linux filesystem, and be at least 8GB. Think about it, and be careful not
to choose a partition that has anything important on it, as the partition
is going to get erased."
echo -n "Press ENTER to continue: "
read goforit
[ "$goforit" != "" ] && exit

echo
echo "Choose the partition to install to..."
CNT=1
echo -n "" > /tmp/quirkytargetparts
for AIMG in $ALLPARTS
do
 echo "${CNT} ${AIMG}" >> /tmp/quirkytargetparts
 CNT=`expr $CNT + 1`
done
cat /tmp/quirkytargetparts
echo
echo -n "Type a number from left column: "
read numimg
[ "$numimg" = "" ] && exit
TARGETPART="$(cat /tmp/quirkytargetparts | head -n ${numimg} | tail -n 1 | cut -f 2 -d ' ')" #ex: sda7
echo "...ok, have chosen ${TARGETPART}"
[ "$TARGETPART" = "" ] && exit #precaution
CHECKPART="$(echo "$ALLPARTS" | tr ' ' '\n' | grep "${TARGETPART}"'$')"
if [ ! "$CHECKPART" ];then
 echo
 echo "Error making choice, aborting."
 exit
fi

###check the target###
#check not mounted...
tPTN="^/dev/${TARGETPART} "
STILL=''
while [ "`mount | grep "$tPTN"`" != "" ];do
 echo
 echo "Partition ${TARGETPART} is ${STILL}mounted."
 echo "Unmount it right now. If you are running one of those Linux distros where
it is not obvious how to unmount a drive, try running this in a terminal:
# umount /dev/${TARGETPART}
Note, the 'mount' command will verify whether unmounted."
 echo -n "Unmount it right now, then press ENTER (CTRL-C to abort): "
 read goforit
 [ "$goforit" != "" ] && exit
 STILL='still '
done
#check f.s....
if which probepart > /dev/null 2>&1;then
 pPTN="^/dev/${TARGETPART}|"
 TARGETFS="$(probepart | grep "$pPTN" | cut -f 2 -d '|')"
else
 TARGETFS="$(blkid /dev/${TARGETPART} | grep -o 'TYPE="[^"]*' | cut -f 2 -d '"')" #'
fi
if [ "$(echo -n "$TARGETFS" | grep -E 'ext2|ext3|ext4|f2fs|reiserfs|xfs|btrfs')" = "" ];then
 echo
 echo "${TARGETPART} has '${TARGETFS}' filesystem, an invalid choice, aborting."
 exit
fi

FSUUID="$(blkid /dev/${TARGETPART} | grep -o 'UUID="[^"]*' | cut -f 2 -d '"')" #'

###write to target###
echo
echo "Now the action is starting, will write to partition ${TARGETPART},
which has filesystem ${TARGETFS}."
echo "Anything previously in the partition will be erased.
Note, if you already have Quirky installed on the partition, and wish to
upgrade it, this is not the script to use. Instead, install a Service Pack PET."
echo -n "Press ENTER to continue (CTRL-C to abort): "
read goforit
[ "$goforit" != "" ] && exit

mkdir -p /mnt/$TARGETPART
mount -t $TARGETFS /dev/$TARGETPART /mnt/$TARGETPART
if [ $? -ne 0 ];then
 echo
 echo "Error, failed to mount ${TARGETPART}, aborting. Maybe you should be running Puppy Linux or Puppy-derivative."
 exit
fi
echo
echo "Erasing contents of ${TARGETPART}..."
rm -rf /mnt/$TARGETPART/*
rm -rf /mnt/$TARGETPART/.* 2> /dev/null
sync

echo
echo "Writing Quirky files to ${TARGETPART}..."
mkdir -p mntpt
mount -t squashfs -o loop,ro ${IMGFILE} mntpt
if [ $? -ne 0 ];then
 echo
 echo "Error mounting ${IMGFILE} on mntpt. Aborting"
 rm -f ${IMGFILE}
 exit
fi
TARGETVERSION="$(grep '^DISTRO_VERSION=' mntpt/etc/DISTRO_SPECS | cut -f 2 -d '=' | cut -f 2 -d "'" | cut -f 1 -d ' ')" #ex: 6.0.1'

#150727
##140212
#echo
#echo "Creating ${FILEPREFIX}-${TARGETVERSION}.sfs"
#echo "This will be copied to /audit/reference in the target drive, and
#may be used in future for recovery purposes. Creating now..."
#rm -f ${FILEPREFIX}-${TARGETVERSION}.sfs 2>/dev/null
#mksquashfs mntpt ${FILEPREFIX}-${TARGETVERSION}.sfs -processors 1
sync

echo
echo "Now writing to ${TARGETPART}, please wait..."
cp -a -f --remove-destination mntpt/* /mnt/$TARGETPART/ 2> /tmp/installquirky-cp-errlog
sync
umount mntpt

#fix f.s.... 151213 no longer required...
#tPTN1="s%.*MARK_DEV1FS_LINE.*% DEV1FS='${TARGETFS}' #MARK_DEV1FS_LINE%"
#tPTN2="s%DEV1FS='f2fs'.*%DEV1FS='${TARGETFS}' #MARK_DEV1FS_LINE%"
#sed -i -e "$tPTN1" /mnt/${TARGETPART}/sbin/init
#sed -i -e "$tPTN2" /mnt/${TARGETPART}/etc/rc.d/rc.sysinit

rm -f ./${IMGFILE} #131227
sync

#150727
##140212
#echo
#echo "Now copying ${FILEPREFIX}-${TARGETVERSION}.sfs to /audit/reference
#in partition ${TARGETPART}, please wait..."
#cp -a -f ${FILEPREFIX}-${TARGETVERSION}.sfs /mnt/${TARGETPART}/audit/reference/
#DATE="$(date +%Y%m%d%H%M)" #140213 141021
#echo "${DATE} ${FILEPREFIX}-${TARGETVERSION}.sfs" > /mnt/${TARGETPART}/audit/reference/dates #140213 141021

#160424 record installed mode. maybe used by /usr/sbin/savesession, installquirky...
echo 'INSTALLED_MODE=full' > /mnt/${TARGETPART}/etc/rc.d/install.log #possible values: livecd, frugal, full

sync
umount /mnt/${TARGETPART}

rm -f ${FILEPREFIX}-${TARGETVERSION}.sfs

#140123 if installed to a removable drive, the grub "root=/dev/$TARGETPART" is not adequate...
TARGETDRIVE="$(echo -n "$TARGETPART" | sed -e 's%[0-9]$%%' -e 's%[0-9]$%%' -e 's%p$%%')" #ex: mmcblk0p1 becomes mmcblk0, sdb12 becomes sdb
TARGETNUM="$(echo -n "$TARGETPART" | rev | grep -o '^[0-9]*' | rev)" #ex: mmcblk0p1 becomes 1, sdb12 becomes 12

#171111 want part-num in hex:
xTARGETNUM="$(printf "%02x" ${TARGETNUM})" #exs: 9 -> 09, 10 -> 0a
[ "`echo -n "$TARGETNUM" | wc -m`" = "1" ] && TARGETNUM="0${TARGETNUM}" #want two digits.

FDISKINFO="$(fdisk -l /dev/${TARGETDRIVE} 2>/dev/null)"
DISKUUID="$(echo "$FDISKINFO" | grep '^Disk identifier:' | tr -s ' ' | cut -f 3 -d ' ' | sed -e 's%^0x%%')" #ex: 2669a57d

echo
echo "That's it, done!"

echo
echo "You will need to configure LILO, GRUB, or whatever boot manager you
use, to boot from this partition. For example, for GRUB4DOS, booting off
partition ${TARGETPART}, put this in menu.lst:

title Quirky ${TARGETVERSION} (full install on ${TARGETPART})
  uuid ${FSUUID}
  kernel /boot/vmlinuz root=PARTUUID=${DISKUUID}-${xTARGETNUM} rootwait rw

Note: The UUID of the filesystem was obtained by running 'blkid /dev/${TARGETPART}'.
Note: 'root=/dev/${TARGETPART}' may not work if the drive is removable, such as
      USB or SD-card, but root=PARTUUID=${DISKUUID}-${xTARGETNUM} will always work.
Note: '${DISKUUID}' is the Disk-UUID, obtained from 'fdisk -l /dev/${TARGETDRIVE}'.
Note: '-${xTARGETNUM}' is the partition number, in hexadecimal.
Note: 'rootwait' is optional, essential for external USB drives.
Note: Unlike Puppy Linux, Quirky only recognises three Quirky-specific kernel
      boot parameters, 'qfix=bak', 'qfix=nox' and 'qfix=fsck'."

###END###
