#!/bin/sh
#(c) Copyright Barry Kauler, 30 January 2017. Licence: GPL v3 (/usr/share/doc/legal).
#simple script in initramfs to boot Easy Linux.
#deloyed as a drive image, with one 640MB fat32 partition, containing vmlinuz, initrd.q, easy.sfs
#text colors: 34=blue, 33=yellow, 32=green, 31=red, 35=purple, 36=aquablue, 38=black
#background colors: 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white

export TEXTDOMAIN=easyinitrd
export OUTPUT_CHARSET=UTF-8
mount -t proc none /proc
mount -t sysfs none /sys
mount -t rootfs -o remount,rw rootfs /
ln -s /proc/mounts /etc/mtab 2> /dev/null
export PATH="/bin:/sbin"

err_exit() {
 echo -e "\\033[1;31mERROR: ${1}\\033[0;39m" #red
 echo 'Have now dropped into a shell in the initramfs.'
 echo 'Note1: Type "exit", the init script will attempt to continue, however,'
 echo '       only an expert who is debugging the bootup should do this.'
 echo 'Note2: On some PCs the keyboard does not work at this stage of bootup.'
 echo 'PLEASE HOLD DOWN THE POWER BUTTON TO SHUTDOWN'
 /bin/sh
}

ask_kb() { #181010
 KEYMAP=us
 echo -e '\e[1;;45m 1 azerty 2 be-latin1  3 br-abnt2  4 br-abnt   5 br-latin1-abnt2 6 br-latin1-us
 7 by     8 cf         9 croat      10 cz       11 de             12 de-latin1 
 13 dk    14 dvorak    15 dvorak-l  16 dvorak-r 17 es             18 et        
 19 fi    20 fr        21 gr        22 hu101    23 hu             24 il        
 25 it    26 jp106     27 la-latin1 28 lt       29 mk             30 nl        
 31 no    32 pl        33 pt-latin1 34 ro       35 ru             36 se        
 37 sg    38 sk-qwerty 39 sk-qwertz 40 slovene  41 srp            42 sv-latin1 
 43 uk    44 us        45 wangbe                                               \e[0;;m'
 echo -e '\e[1;;44m Please enter the number corresponding to your keyboard layout.   
 Choose the closest match, there will an opportunity to fine-tune 
 the layout after the desktop has loaded. Press ENTER only for US.\e[0;;m'
 echo -e '\e[1;30;43m Note: on some PCs the keyboard does not work at this stage of bootup. 
 In that case, wait 5 minutes for bootup.                              \e[0;;m'
 echo -n " Keyboard layout: "
 read -r -t 300 KBnum
 [ $? -ne 0 ] && return 1 #timed out
 KBnum=$(echo -n "$KBnum" | sed -e 's%[^0-9]%%g')
 [ ! $KBnum ] && KBnum=44
 [ $KBnum -gt 45 ] && KBnum=44
 [ $KBnum -eq 0 ] && KBnum=44
 KEYMAP="$(ls -1 /lib/keymaps | head -n ${KBnum} | tail -n 1 | sed -e 's%\.gz%%')"
 echo " ...ok, ${KEYMAP} chosen"
 return 0
}

ask_pw() { #180604
 if [ "$1" == "0" ];then
  echo -e '\e[1;;44m Please enter a password, any characters a-z, A-Z, 0-9, any length. 
 The password will encrypt parts of the working-partition, and must 
 be remembered, as it will have to be entered at every bootup.      
 Or, just press ENTER key for no password.                          \e[0;;m'
#  echo -e '\e[1;30;43m Note: on some PCs the keyboard does not work at this stage of bootup. 
# In that case, wait 5 minutes for bootup with no password.             \e[0;;m'
  while [ 1 ];do #181109
   echo -n " Password: "
   read -r -t 300 PW
   [ $? -ne 0 ] && echo #timed out
   if [ "$PW" != "" ];then
    xPW="$(echo -n "$PW" | sed -e 's%[^a-zA-Z0-9]%%g')"
    if [ "$PW" != "$xPW" ];then
     echo "\\033[1;31m Sorry, only a-z, A-Z, 0-9 characters allowed, try again \\033[0;39m" #red text.
     continue
    fi
   fi
   break
  done
#  if [ ! "$PW" ];then
#   PW="$(< /dev/urandom tr -dc 'a-zA-Z0-9' | head -c10)"
#   echo " The auto-generated password is: ${PW}"
#   echo " Pausing for 60 seconds, please write it down now!!!!"
#   sleep 60
#  fi
 else
  #echo -e '\e[1;;44m Please enter password to decrypt the working-partition \e[0;;m'
  echo -e '\e[1;;44m Please enter password to decrypt the working-partition \e[0;;m'
  echo -n " Password: "
  #read PW
  PW=''
  while [ 1 ];do #echo * for each char entered...
   read -r -s -n1 pw1
   if [[ -z $pw1 ]];then
    echo; break
   else
    echo -n '*'; PW="${PW}${pw1}"
   fi
  done
 fi
 #if [ "$PW" ];then
 # PWlen=$(echo -n "$PW" | wc -m)
 # [ $PWlen -lt 16 ] && PW=${PW}`seq -s '' ${PWlen} 16` #pad to 16 chars.
 #fi
}

#170206 reintroducing aufs in the kernel:
if grep -qw aufs /proc/filesystems; then
 LAYERFS='aufs'
 RO='=ro'
else
 LAYERFS='overlay'
 RO=''
fi

SESSIONSFSflag=0 #170525 see also /usr/sbin/easy_version_control. 170924 change 1 to 0.
export SESSIONSFSflag

###find drives###
#find the drive we are booting on (has vmlinuz, initrd.q, easy.sfs), and working drv...
#181029 BOOT_SPECS, created in 3buildeasydistro, now also has Q_DISTRO_BINARY_COMPAT, Q_DISTRO_COMPAT_VERSION ex: oe, pyro
. /BOOT_SPECS #has BOOT_DISKID, BOOT_PARTNUM, BOOT_FS, BOOT_DIR, WKG_DISKID, WKG_PARTNUM, WKG_FS, WKG_DIR, Q_DISTRO_VERSION
#180601 users may forget to put a trailing slash... a leading slash is not allowed...
[ "$BOOT_DIR" ] && [ "${BOOT_DIR##*/}" ] && BOOT_DIR="${BOOT_DIR}/"
[ "$WKG_DIR" ] && [ "${WKG_DIR##*/}" ] && WKG_DIR="${WKG_DIR}/"
[ "$BOOT_DIR" ] && [ "${BOOT_DIR:0:1}" == "/" ] && BOOT_DIR="${BOOT_DIR:1:99}"
[ "$WKG_DIR" ] && [ "${WKG_DIR:0:1}" == "/" ] && WKG_DIR="${WKG_DIR:1:99}"

echo -n -e "\\033[1;35mFinding drives\\033[0;39m\n " #purple
CNT=0; Pb=''; Pw=''; BOOT_DRV=''; WKG_DRV=''

if [ $WKG_PARTNUM -eq 0 ];then #zram0
 FREEK=`grep '^MemFree:' /proc/meminfo | tr -s ' ' | cut -f 2 -d ' '`
 #allocate 3/4 of free ram times 2 (as compression is approx 2:1)...
 HALFK=$(($FREEK/2))
 QTRK=$(($HALFK/2))
 USEK=$(($HALFK+$QTRK)) #3/4
 ALLOCK=$(($USEK*2))
 echo "  Creating compressed zram, using ${USEK}K of RAM"
 echo "${ALLOCK}K" > /sys/block/zram0/disksize
 echo "${USEK}K" > /sys/block/zram0/mem_limit
 WKG_DRV='zram'
 WKG_DISKID='unknown'
 WKG_FS='ext4'
fi

while [ $CNT -lt 20 ];do #drives may take couple seconds to become available. 180415 increase 8 to 20.
 sleep 1
 CNT=$(($CNT+1))
 for aDRV in /sys/block/sd[a-z] /sys/block/mmcblk[0-9] /sys/block/nvme[0-9]n1 #180408 nvme
 do
  [ "${aDRV/*]/]}" == "]" ] && continue #170731
  [ "${aDRV/*]/]}" == "]n1" ] && continue #180408
  DRV=${aDRV:11:7} #extract drv from /sys/block/<drv>
  echo -n " ${DRV}"
  fdisk -l /dev/${DRV} > diskinfo-${DRV} 2>/dev/null
  if grep "$BOOT_DISKID" diskinfo-${DRV} >/dev/null;then BOOT_DRV="$DRV"; fi
  if grep "$WKG_DISKID" diskinfo-${DRV} >/dev/null;then WKG_DRV="$DRV"; fi
  [ "$BOOT_DRV" -a "$WKG_DRV" ] && break 2
 done
done
[ ! "$BOOT_DRV" ] && err_exit 'Boot drive not found'
[ ! "$WKG_DRV" ] && err_exit 'Working drive not found'
[ "${BOOT_DRV:0:3}" == "mmc" ] && Pb='p'
[ "${WKG_DRV:0:3}" == "mmc" ] && Pw='p'
[ "${BOOT_DRV:0:3}" == "nvm" ] && Pb='p' #180408 nvme
[ "${WKG_DRV:0:3}" == "nvm" ] && Pw='p'  #180408 nvme
BOOT_DEV="${BOOT_DRV}${Pb}${BOOT_PARTNUM}"
WKG_DEV="${WKG_DRV}${Pw}${WKG_PARTNUM}"
echo -e "\n  Boot-partition: ${BOOT_DEV}  Working-partition: ${WKG_DEV}"
mkdir -p /mnt/${BOOT_DEV}
mkdir -p /mnt/${WKG_DEV}

###performance measurements###
FREEK=`grep '^MemFree:' /proc/meminfo | tr -s ' ' | cut -f 2 -d ' '` #free RAM
#echo 3 > /proc/sys/vm/drop_caches #clear memory caches. note, could use "hdparm -t ..." but it is slower.
if [ "$WKG_DRV" == "zram" ];then #180610
 TIMEs="$(dd if=/dev/ram of=/dev/null bs=1024 count=64 iflag=skip_bytes skip=1048576 2>&1 | grep -o '[0-9.]* seconds,' | cut -f 1 -d ' ')" #read speed.
else
 TIMEs="$(dd if=/dev/${WKG_DRV} of=/dev/null bs=1024 count=64 iflag=skip_bytes skip=1048576 2>&1 | grep -o '[0-9.]* seconds,' | cut -f 1 -d ' ')" #read speed.
fi
TIME10k=$(dc ${TIMEs} 10000 mul p | cut -f 1 -d '.') #cheap flash stick: usb2=140 usb3=77, be usb3=41, sandisk-extreme usb3=42, internal eMMC: 

###[create and] mount working partition###
E4flg=''; PW=''
grep -v 'zram' /proc/partitions > partitions #180610
if ! grep " ${WKG_DEV}$" partitions >/dev/null;then
 if [ $WKG_PARTNUM -ne 0 ];then
  echo -e "\\033[1;35mCreating partition ${WKG_DEV} to fill drive\\033[0;39m" #purple
  #170730 now mbr, not gpt, need to specify primary (p) or extended (e)...
  echo -e "n\np\n${WKG_PARTNUM}\n\n\nw" | fdisk -u /dev/$WKG_DRV > err.log 2>&1
  sync
  if grep -i 'failed' err.log ;then err_exit "Failed to create working partition ${WKG_DEV}" ; fi
 fi
 echo "  Creating ${WKG_FS} filesystem in partition ${WKG_DEV}"
 mke2fs -F -q -t ${WKG_FS} -O encrypt,^has_journal -L easy2 -m 0 -b 4096 /dev/${WKG_DEV} #only supporting ext2/3/4
 E4flg='yes'
else #180605
 E4flg="$(blkid /dev/${WKG_DEV} | grep -o 'TYPE="ext4"')"
# #all of this is for a pre-existing f.s., say a frugal install...
# #check the filesystem is ext4 and encrypt enabled...
# E4flg="$(blkid /dev/${WKG_DEV} | grep -o 'TYPE="ext4"')"
# if [ "$E4flg" == "" ];then
#  echo -e "\\033[1;31mWorking-partition not ext4, cannot encrypt. You will not be asked for a password.\\033[0;39m" #red
#  PWflg='no'
# else
#  ENCRflg="$(tune2fs -l /dev/${WKG_DEV} | grep '^Filesystem features: ' | grep -o 'encrypt')"
#  if [ "$ENCRflg" == "" ];then
#   echo -e '\n\[1;;31m WARNING: Encryption is not enabled on the working-partition.   
#          Press ENTER to enable, or any other character not to. \[0;;m'
#   echo -n ' Press ENTER to enable: '
#   read eenable
#   if [ "$eenable"== "" ];then
#    tune2fs -O encrypt /dev/${WKG_DEV}
#    if [ $? -eq 0 ];then
#     echo -e "\\033[1;32mEncryption capability enabled on working-partition\\033[0;39m" #green
#    else
#     echo -e "\\033[1;31mFailed to enabled encryption. You will not be asked for a password.\\033[0;39m" #red
#     PWflg='no'
#    fi
#   else
#    echo -e "\\033[1;31mYou chose not to enable encryption. You will not be asked for a password.\\033[0;39m" #red
#    PWflg='no'
#   fi
#  fi
# fi
fi
mount -t ${WKG_FS} /dev/${WKG_DEV} /mnt/${WKG_DEV}
[ $? -ne 0 ] && err_exit "Unable to mount working-partition ${WKG_DEV}"
if [ ! -d /mnt/${WKG_DEV}/${WKG_DIR}releases ];then #populate with skeleton directory hierarchy.
 touch /mnt/${WKG_DEV}/${WKG_DIR}CONFIG
 mkdir /mnt/${WKG_DEV}/${WKG_DIR}containers
 mkdir /mnt/${WKG_DEV}/${WKG_DIR}releases
 mkdir /mnt/${WKG_DEV}/${WKG_DIR}home
 mkdir /mnt/${WKG_DEV}/${WKG_DIR}sfs #181028
 mkdir /mnt/${WKG_DEV}/${WKG_DIR}.session
 mkdir /mnt/${WKG_DEV}/${WKG_DIR}.tempwork
 PW=''; KEYMAP=us
 if [ "$E4flg" ];then #180605
  echo
  ask_kb #181010 sets $KEYMAP
  if [ $? -eq 0 ];then #181010
   gunzip -c /lib/keymaps/${KEYMAP}.gz | loadkmap
   ask_pw 0 #sets $PW
  fi
  echo
  if [ "$PW" ];then
   POLICY="$(echo "$PW" | e4crypt add_key -S "s:${WKG_DISKID}" | tail -n 1 | cut -f 2 -d '[' | cut -f 1 -d ']')"
   #181013 too much performance hit, only encrypt 'home' folder... 181028 revert...
   e4crypt set_policy ${POLICY} /mnt/${WKG_DEV}/${WKG_DIR}containers
   e4crypt set_policy ${POLICY} /mnt/${WKG_DEV}/${WKG_DIR}releases
   e4crypt set_policy ${POLICY} /mnt/${WKG_DEV}/${WKG_DIR}home
   e4crypt set_policy ${POLICY} /mnt/${WKG_DEV}/${WKG_DIR}.session
  fi
 fi
 cp -a -f /skeleton/containers /mnt/${WKG_DEV}/${WKG_DIR}
 #181012 populate .session folders...
 for aCONT in `ls -1 /skeleton/containers`
 do
  cp -a -f /skeleton/containers/${aCONT}/.sessionSKEL/* /mnt/${WKG_DEV}/${WKG_DIR}containers/${aCONT}/.session/
  [ -d /skeleton/containers/${aCONT}/.sessionSKEL/.control ] && cp -a -f /skeleton/containers/${aCONT}/.sessionSKEL/.control /mnt/${WKG_DEV}/${WKG_DIR}containers/${aCONT}/.session/ #181121
 done
 cp -a -f /skeleton/releases /mnt/${WKG_DEV}/${WKG_DIR}
 cp -a -f /skeleton/home /mnt/${WKG_DEV}/${WKG_DIR}
 cp -a -f /skeleton/sfs /mnt/${WKG_DEV}/${WKG_DIR} #181028
 #cp -a -f /skeleton/.[a-z]* /mnt/${WKG_DEV}/${WKG_DIR}
 echo "KEYMAP='${KEYMAP}'" > /mnt/${WKG_DEV}/${WKG_DIR}CONFIG
else
 POLICYflg="$(e4crypt get_policy /mnt/${WKG_DEV}/${WKG_DIR}home | grep -o '^Error')" #"Error" if no encryption.
 if [ "$POLICYflg" == "" ];then
  touch /mnt/${WKG_DEV}/${WKG_DIR}CONFIG
  . /mnt/${WKG_DEV}/${WKG_DIR}CONFIG
  [ ! "$KEYMAP" ] && KEYMAP=us
  gunzip -c /lib/keymaps/${KEYMAP}.gz | loadkmap
  echo
  while [ 1 ];do
   ask_pw 1 #sets $PW
   POLICY="$(echo "$PW" | e4crypt add_key -S "s:${WKG_DISKID}" | tail -n 1 | cut -f 2 -d '[' | cut -f 1 -d ']')"
   [  -d /mnt/${WKG_DEV}/${WKG_DIR}home/downloads ] && break
   echo -e '\n\e[1;30;43m Password incorrect. Try again \e[0;;m'
  done
  echo
 fi
fi
if [ "$PW" ];then
 if [ ! -s /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/keymap ];then
  mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}.session/etc
  echo -n "$KEYMAP" > /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/keymap
 fi
fi

###set date and time###
#could read .session/etc/clock and run hwclock, but for now this probably good enough (refer: rc.shutdown)...
[ -s /mnt/${WKG_DEV}/${WKG_DIR}.session/root/.var/local/shutdown_date_saved ] && date -s "`cat /mnt/${WKG_DEV}/${WKG_DIR}.session/root/.var/local/shutdown_date_saved`" > /dev/null

###mount boot partition###
if [ "$BOOT_DEV" != "$WKG_DEV" ];then
 mount -t ${BOOT_FS} /dev/$BOOT_DEV /mnt/$BOOT_DEV
 [ $? -ne 0 ] && err_exit "Unable to mount boot-partition ${BOOT_DEV}"
fi
[ ! -f /mnt/$BOOT_DEV/${BOOT_DIR}easy.sfs ] && err_exit "Boot-partition does not have file easy.sfs"
KERNELNAME=vmlinuz
[ -f /mnt/$BOOT_DEV/${BOOT_DIR}kernel8.img ] && KERNELNAME=kernel8.img #rpi3
export KERNELNAME

###recovery, maintenance###
[ "$qfix" ] && QFIX=$qfix #kernel boot param
if [ "$QFIX" ];then
 for ONEFIX in `echo -n "$QFIX" | tr ',' ' '`
 do
  case $ONEFIX in
   fsck|FSCK) echo -n "${WKG_DEV},${WKG_FS},REQUEST" > /mnt/${WKG_DEV}/${WKG_DIR}.session/.fsckme.flg ;;
   back|bak|BACK|BAK) echo -n ",last" > /mnt/${WKG_DEV}/${WKG_DIR}.session/.rollback.flg ;;
   new) echo -n ",erase" > /mnt/${WKG_DEV}/${WKG_DIR}.session/.rollback.flg ;; #181009
  esac
 done
fi
export wkgLANG="$(grep '^LANG=' /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/profile 2>/dev/null | cut -f 2 -d '=')"
[ ! "$wkgLANG" ] && export wkgLANG=C
[ -s /mnt/${WKG_DEV}/${WKG_DIR}.session/.fsckme.flg ] && fscheck ${WKG_DRV} ${WKG_DEV} #ex: improper shutdown
[ -s /mnt/${WKG_DEV}/${WKG_DIR}.session/.rollback.flg ] && rollback ${WKG_DRV} ${WKG_DEV} ${BOOT_DRV} ${BOOT_DEV} #180602

###version control###
prevVER="" #170919
if [ ! -d /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION} ];then
 echo -e "\\033[1;35m$(LANG=${wkgLANG} gettext 'One-time only operation, creating a snapshot of EasyOS')\\033[0;39m"
 echo "  $(LANG=${wkgLANG} gettext 'This will allow future rollback with the Easy Version Control Manager')"
 echo "  $(LANG=${wkgLANG} gettext 'Creating:') /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}"
 mkdir /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}
 
 #170816 there is a limit on history...
 if [ -s /mnt/${WKG_DEV}/${WKG_DIR}.session/root/.var/local/version-history-depth ];then
  DEPTH_MAX="$(cat /mnt/${WKG_DEV}/${WKG_DIR}.session/root/.var/local/version-history-depth)"
  VERS="$(ls -l /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-* | rev | cut -f 1 -d '-' | rev)"
  sortedVERS="$(echo "$VERS" | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n)" #lowest to highest.
  for ADEL in `echo "$sortedVERS" | head -n -${DEPTH_MAX} | tr '\n' ' '`
  do
   if [ -d /mnt/${WKG_DEV}/${WKG_DIR}repositories/easy-${ADEL} ];then
    MSGdel="$(gettext 'Warning, deleting old version:')"
    echo -e "  \\033[1;31m${MSGdel} easy-${ADEL}\\033[0;39m" #red
    rm -rf /mnt/${WKG_DEV}/${WKG_DIR}repositories/easy-${ADEL}
   fi
  done
 fi

 if [ -f /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/DISTRO_SPECS ];then
  prevVER="$(grep '^DISTRO_VERSION=' /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/DISTRO_SPECS | cut -f 2 -d '=' | cut -f 1 -d ' ')"
  touch /mnt/${WKG_DEV}/${WKG_DIR}.session/.delayedrun_version_upgrade #see /usr/sbin/delayedrun
 else
  prevVER=""
 fi
 echo -n '  initrd.q'; cp -f /mnt/${BOOT_DEV}/${BOOT_DIR}initrd.q /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/
 echo -n " ${KERNELNAME}"; cp -f /mnt/${BOOT_DEV}/${BOOT_DIR}${KERNELNAME} /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/
 
 #181029 all .sfs files are now in /mnt/wkg/sfs, with symlinks (to avoid being encrypted)...
 #echo -n ' easy.sfs'; cp -f /mnt/${BOOT_DEV}/${BOOT_DIR}easy.sfs /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/
 mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}sfs/easyos/${Q_DISTRO_BINARY_COMPAT}/${Q_DISTRO_COMPAT_VERSION} #ex: oe/pyro
 echo -n ' easy.sfs'; cp -f /mnt/${BOOT_DEV}/${BOOT_DIR}easy.sfs /mnt/${WKG_DEV}/${WKG_DIR}sfs/easyos/${Q_DISTRO_BINARY_COMPAT}/${Q_DISTRO_COMPAT_VERSION}/easy_${Q_DISTRO_VERSION}_${Q_DISTRO_TARGETARCH}.sfs
 ln -s ../../sfs/easyos/${Q_DISTRO_BINARY_COMPAT}/${Q_DISTRO_COMPAT_VERSION}/easy_${Q_DISTRO_VERSION}_${Q_DISTRO_TARGETARCH}.sfs /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/easy.sfs
 
 rm -rf /mnt/${WKG_DEV}/${WKG_DIR}.session/.[a-z]* 2>/dev/null #precaution.
 ##170919 delete *all* whiteout files (see also /sbin/fixlayers)...
 #find /mnt/${WKG_DEV}/${WKG_DIR}.session -mindepth 1 -type f -name '.wh.*' -delete 2>/dev/null
 if [ $SESSIONSFSflag -eq 1 ];then #170525
  if [ ! "$prevVER" ];then
   #.session folder (rw layer) is empty, but need a session.sfs anyway...
   echo -n ' session'; mksquashfs /mnt/${WKG_DEV}/${WKG_DIR}.session /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/session.sfs -comp gzip >/dev/null
  else
   #need to merge .session (rw layer) with easy-$prevVER/session.sfs, create new session.sfs...
   mkdir sro snew
   mount -t squashfs -o loop,noatime /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${prevVER}/session.sfs sro
   [ $? -ne 0 ] && err_exit "FAILED: mount -t squashfs -o loop,noatime /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${prevVER}/session.sfs sro"
   if [ "$LAYERFS" == "aufs" ];then
    mount -t aufs -o br=/mnt/${WKG_DEV}/${WKG_DIR}.session=rw:sro=ro aufs snew
    [ $? -ne 0 ] && err_exit "FAILED: mount -t aufs -o br=/mnt/${WKG_DEV}/${WKG_DIR}.session=rw:sro=ro aufs snew"
   else
    mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}swork
    mount -t overlay -o lowerdir=sro,upperdir=/mnt/${WKG_DEV}/${WKG_DIR}.session,workdir=/mnt/${WKG_DEV}/${WKG_DIR}swork overlay snew
    [ $? -ne 0 ] && err_exit "mount -t overlay -o lowerdir=sro,upperdir=/mnt/${WKG_DEV}/${WKG_DIR}.session,workdir=/mnt/${WKG_DEV}/${WKG_DIR}swork overlay snew"
   fi
   #180606 need path root/.XLOADED  181121 exclude .control
   echo -e 'dev\nmnt\nproc\nrun\nsys\ntmp\nvar\nlost+found\nroot/.XLOADED\n.control' > exclusions1 #exclusions.
   mksquashfs snew /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/session.sfs -ef exclusions1 -comp gzip #>/dev/null
   echo -e "\\033[1;33m$(LANG=${wkgLANG} gettext 'Please wait, synchronizing...')\\033[0;39m" #yellow
   sync
   umount snew
   umount sro
   [ -d /mnt/${WKG_DEV}/${WKG_DIR}swork ] && rm -rf /mnt/${WKG_DEV}/${WKG_DIR}swork
   rm -rf /mnt/${WKG_DEV}/${WKG_DIR}.session/*
   rm -f /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${prevVER}/session.sfs #remove session.sfs in prev. version.
  fi
 else
  #echo -n "rw-${Q_DISTRO_VERSION}.sfs"; 
  mksquashfs /mnt/${WKG_DEV}/${WKG_DIR}.session /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/rw-${Q_DISTRO_VERSION}.sfs -comp gzip #>/dev/null
 fi
 mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}.session/etc
 #also save any container sessions:
 for EXE in `ls -1 /mnt/${WKG_DEV}/${WKG_DIR}containers | tr '\n' ' '`
 do
  [ ! -d /mnt/${WKG_DEV}/${WKG_DIR}containers/${EXE}/.session ] && continue
  #echo -n " ec-${EXE}"; mksquashfs /mnt/${WKG_DEV}/${WKG_DIR}containers/${EXE}/.session /mnt/${WKG_DEV}/${WKG_DIR}containers/${EXE}/rw-${prevVER}.sfs -comp gzip >/dev/null
  cp -f /mnt/${WKG_DEV}/${WKG_DIR}containers/${EXE}/configuration /mnt/${WKG_DEV}/${WKG_DIR}containers/${EXE}/configuration-${Q_DISTRO_VERSION}
 done
 echo
 touch /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/configuration
 touch /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/configuration-${Q_DISTRO_VERSION}
 #180602 fix version number in syslinux.cfg and refind.conf...
 [ -f /mnt/${BOOT_DEV}/syslinux.cfg ] && sed -i -e "s%^menu title .*%menu title EasyOS ${Q_DISTRO_VERSION}%" /mnt/${BOOT_DEV}/syslinux.cfg
 [ -f /mnt/${BOOT_DEV}/EFI/BOOT/refind.conf ] && sed -i -e "s%EasyOS .* normal bootup%EasyOS ${Q_DISTRO_VERSION} normal bootup%" /mnt/${BOOT_DEV}/EFI/BOOT/refind.conf
fi

###recompress easy.sfs### improve operating speed, recompress easy.sfs (refer quicksetup)
if [ -s /mnt/${WKG_DEV}/${WKG_DIR}.session/.qsfs.flg ];then #181029 now in sfs folder...
 echo -e "\\033[1;35m$(LANG=${wkgLANG} gettext 'Recompressing easy.sfs, xz to gz, please wait')\\033[0;39m" #purple
 mkdir /mntsfs
 mount -r -t squashfs -o loop,noatime /mnt/${WKG_DEV}/${WKG_DIR}sfs/easyos/${Q_DISTRO_BINARY_COMPAT}/${Q_DISTRO_COMPAT_VERSION}/easy_${Q_DISTRO_VERSION}_${Q_DISTRO_TARGETARCH}.sfs /mntsfs
 mksquashfs /mntsfs /mnt/${WKG_DEV}/${WKG_DIR}sfs/easyos/${Q_DISTRO_BINARY_COMPAT}/${Q_DISTRO_COMPAT_VERSION}/easy-gz.sfs -comp gzip #>/dev/null 180604
 sync
 umount /mntsfs
 mv -f /mnt/${WKG_DEV}/${WKG_DIR}sfs/easyos/${Q_DISTRO_BINARY_COMPAT}/${Q_DISTRO_COMPAT_VERSION}/easy-gz.sfs /mnt/${WKG_DEV}/${WKG_DIR}sfs/easyos/${Q_DISTRO_BINARY_COMPAT}/${Q_DISTRO_COMPAT_VERSION}/easy_${Q_DISTRO_VERSION}_${Q_DISTRO_TARGETARCH}.sfs
 sync
 rm -f /mnt/${WKG_DEV}/${WKG_DIR}.session/.qsfs.flg
fi

###setup bottom ro layer, with easy.sfs###
echo -e "\\033[1;35m$(LANG=${wkgLANG} gettext 'Mounting read-only layer of layered filesystem')\\033[0;39m" #purple
QSFSbytes0=`stat -L -c %s /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/easy.sfs` #181029
QSFSbytes1=$(($QSFSbytes0+500000))
mount -t tmpfs -o size=${QSFSbytes1} tmpfs /easy_ro
mkdir /easy_ro/easy_sfs
#decide whether to copy easy.sfs to RAM, or not...
CPYflg=0
[ $FREEK -gt 1100000 ] && CPYflg=1 #>1GB ram then copy
[ $TIME10k -lt 100 ] && CPYflg=0   #but fast drive so don't copy.
[ $FREEK -gt 3100000 ] && CPYflg=1 #but heaps of ram, so copy. 181120 restore.
[ $TIME10k -lt 30 ] && CPYflg=0    #181120 but super-fast drive so don't copy.
if [ $CPYflg -eq 0 ];then
 #do not copy easy.sfs into ram, mount where it is...
 echo "  $(LANG=${wkgLANG} gettext 'Mounting squashfs file easy.sfs')"
 QSFS_PATH="/mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/" #need this for setting up containers.
 mount -r -t squashfs -o noatime,loop /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/easy.sfs /easy_ro/easy_sfs
else
 echo "  $(LANG=${wkgLANG} gettext 'Copying easy.sfs to RAM, then mounting')"
 [ ! -f /easy_ro/easy.sfs ] && cp -L /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/easy.sfs /easy_ro/ #181029
 QSFS_PATH="/mnt/easy_ro/" #need this for setting up containers.
 mount -r -t squashfs -o noatime,loop /easy_ro/easy.sfs /easy_ro/easy_sfs
fi
[ $? -ne 0 ] && err_exit "$(LANG=${wkgLANG} gettext 'Failed to mount easy.sfs')"
mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}.session/etc #170927 missing if have erased session.
cp -f /easy_ro/easy_sfs/etc/DISTRO_SPECS /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/ #need to be sure correct one is on top.
EXTRASFS=""; sessionSFS=""; NEWEXTRASFSLIST=""
if [ $SESSIONSFSflag -eq 1 ];then #170525
 mkdir /easy_ro/session
 mount -r -t squashfs -o loop,noatime /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/session.sfs /easy_ro/session
 sessionSFS="/easy_ro/session${RO}:"
fi
#precaution...
. /easy_ro/easy_sfs/etc/DISTRO_SPECS
[ "$DISTRO_VERSION" != "$Q_DISTRO_VERSION" ] && echo -e "\\033[1;31m$(gettext 'WARNING, versions do not match.') initrd.q: ${Q_DISTRO_VERSION}, easy.sfs: ${DISTRO_VERSION}\\033[0;39m" #red

###load extra sfs on ro layer###
#the configuration file defines any more sfs files to load. easy.sfs is always loaded
# (on bottom), and session.sfs on top of ro layers.
. /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/configuration
for NUM in 4 3 2 1
do
 eval "ROsfs=\$EASY_LAYER_RO${NUM}" #implements indirection. EASY_LAYER_RO1='devx*.sfs' in configuration file, will assign 'devx*.sfs' to ROsfs. 170320 170523
 if [ "$ROsfs" ];then
  #170523 check file exists. note, may have a glob wildcard...
  #181029 no longer have wildcard. ex: devx.sfs which is a symlink into 'sfs' folder...
  FNDSFSS="$(ls -1 /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/${ROsfs} | tr '\n' ' ')"
  for FNDSFS in $FNDSFSS
  do
   ANAME="$(basename $FNDSFS .sfs)" #ex: devx
   NAMEONLY="${ANAME/_*/}" #181029 precaution.
   #181029 all .sfs files must be under sfs folder, to avoid encryption (except for rw-*.sfs)...
   # this is a precaution, should already be done...
   if [ "$ANAME" != "$NAMEONLY" ];then
    mv -f /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/${ANAME}.sfs /mnt/${WKG_DEV}/${WKG_DIR}sfs/easyos/${Q_DISTRO_BINARY_COMPAT}/${Q_DISTRO_COMPAT_VERSION}/
    ln -snf ../../sfs/easyos/${Q_DISTRO_BINARY_COMPAT}/${Q_DISTRO_COMPAT_VERSION}/${ANAME}.sfs /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/${NAMEONLY}.sfs
    ANAME="$NAMEONLY"
   fi
   mkdir /easy_ro/$ANAME
   echo "  $(LANG=${wkgLANG} gettext 'Mounting extra squashfs file:') ${ANAME}.sfs"
   mount -r -t squashfs -o noatime,loop /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${Q_DISTRO_VERSION}/${ANAME}.sfs /easy_ro/${ANAME}
   EXTRASFS="/easy_ro/${ANAME}${RO}:${EXTRASFS}" #170206
   NEWEXTRASFSLIST="${ANAME}:${NEWEXTRASFSLIST}" #170919
  done
 fi
done

sync
[ "$BOOT_DEV" != "$WKG_DEV" ] && umount /dev/${BOOT_DEV}

if [ "$PW" ];then
 #180612 set password for zeus... 180811 also root...
 if [ ! -f /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/shadow ];then
  echo -e "\\033[1;35m$(LANG=${wkgLANG} gettext 'First-bootup security setup...')\\033[0;39m" #purple
  echo "  $(LANG=${wkgLANG} gettext 'Setting same password for users zeus and root')"
  ePW="$(cryptpw -m SHA512 ${PW})" #note: busybox mkpasswd is an alias for cryptpw
  grep -v '^zeus' /easy_ro/easy_sfs/etc/shadow > /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/shadow
  echo "zeus:${ePW}:17693:0:99999:7:::" >> /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/shadow
  grep -v '^root' /easy_ro/easy_sfs/etc/shadow > /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/shadow
  echo "root:${ePW}:17693:0:99999:7:::" >> /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/shadow
  for aCONT in `ls -1 /mnt/${WKG_DEV}/${WKG_DIR}containers` #desk console ssh0 www
  do
   cp -a -f /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/shadow /mnt/${WKG_DEV}/${WKG_DIR}containers/${aCONT}/.session/etc/
  done
 fi
 #180615 generate signed key pair..
 if [ ! -d /mnt/${WKG_DEV}/${WKG_DIR}.session/root/.gnupg ];then
  echo "  $(LANG=${wkgLANG} gettext 'Creating gnugpg signed key pair, at /root/.gnupg')"
  mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}.session/root/.gnupg
  chmod 700 /mnt/${WKG_DEV}/${WKG_DIR}.session/root/.gnupg
  cat >foo <<EOF
Key-Type: RSA
Key-Length: 2048
Subkey-Type: RSA
Subkey-Length: 2048
Name-Real: EasyOS user ${RANDOM}
Name-Comment: password is the passphrase
Name-Email: noone@nowhere.com
Expire-Date: 0
Passphrase: ${PW}
%commit
%echo done
EOF
  GNUPGHOME="/mnt/${WKG_DEV}/${WKG_DIR}.session/root/.gnupg" gpg --batch --gen-key foo
 fi
fi



###fix layers change###
OLDEXTRASFSLIST="$(grep '^EXTRASFSLIST=' /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/rc.d/PUPSTATE 2>/dev/null | cut -f 2 -d "'")"
[ -s /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/rc.d/PUPSTATE ] && [ "$NEWEXTRASFSLIST" != "$OLDEXTRASFSLIST" -o "$prevVER" != "" ] && /sbin/fixlayers ${WKG_DRV} ${WKG_DEV} "${NEWEXTRASFSLIST}" "${prevVER}" #170919

###the big moment, create layered f.s.###
#echo -e "\\033[1;35m$(LANG=${wkgLANG} gettext 'Creating layered filesystem, with read-write folder:') /mnt/${WKG_DEV}/.session\\033[0;39m"
echo -e "\\033[1;35m$(LANG=${wkgLANG} gettext 'Creating layered filesystem, type:') ${LAYERFS}\\033[0;39m"
if [ "$LAYERFS" == "aufs" ];then #170525
 mount -t aufs -o br=/mnt/${WKG_DEV}/${WKG_DIR}.session=rw:${sessionSFS}${EXTRASFS}/easy_ro/easy_sfs=ro aufs /easy_new
else
 mount -t overlay -o lowerdir=${sessionSFS}${EXTRASFS}/easy_ro/easy_sfs,upperdir=/mnt/${WKG_DEV}/${WKG_DIR}.session,workdir=/mnt/${WKG_DEV}/${WKG_DIR}.tempwork overlay /easy_new
fi
[ $? -ne 0 ] && err_exit "$(LANG=${wkgLANG} gettext 'Failed to create layered filesystem')"

#/etc/rc.d/rc.sysinit will append to PUPSTATE, get the ball rolling here...
#PUPMODE, bit-1 (partition has session), bit-2 (bottom layer is sfs) --rough equiv to puppy
echo -e "PUPMODE=6\nBOOT_DEV='${BOOT_DEV}'\nBOOT_FS='${BOOT_FS}'\nBOOT_DIR='${BOOT_DIR}'\nWKG_DEV='${WKG_DEV}'\nWKG_FS='${WKG_FS}'\nWKG_DIR='${WKG_DIR}'\nQSFS_PATH='${QSFS_PATH}'" > /easy_new/etc/rc.d/PUPSTATE
echo -e "EXTRASFSLIST='${NEWEXTRASFSLIST}'\nSESSIONSFSflag=${SESSIONSFSflag}" >> /easy_new/etc/rc.d/PUPSTATE #170919 170924

#echo "BOOT_PW_FLG='${PW//[a-zA-Z0-9]/X}'" >> /easy_new/etc/rc.d/PUPSTATE #180811 a flag so main f.s. will know if a pw was entered.
echo "BOOT_PW_FLG='${PW/*/X}'" >> /easy_new/etc/rc.d/PUPSTATE #180811 set to "X" if $PW has something in it. note, used in /usr/local/EasyShare

###relocate mount-points prior to switch_root###
echo -e "\\033[1;35m$(LANG=${wkgLANG} gettext 'Performing a switch_root onto the layered filesystem')\\033[0;39m" #purple
#move the mount points...
[ ! -d /easy_new/mnt/easy_ro ] && mkdir /easy_new/mnt/easy_ro
[ ! -d /easy_new/mnt/${WKG_DEV} ] && mkdir /easy_new/mnt/${WKG_DEV}
[ ! -d /easy_new/mnt/${BOOT_DEV} ] && mkdir /easy_new/mnt/${BOOT_DEV}
mount -o move /easy_ro /easy_new/mnt/easy_ro
mount -o move /mnt/${WKG_DEV} /easy_new/mnt/${WKG_DEV}

mount -t devtmpfs devtmpfs /easy_new/dev #need to do this before switch_root.
sync
umount /sys
umount /proc
exec switch_root /easy_new /sbin/init

###END###
