#!/bin/sh
#(c) Copyright Barry Kauler 2012, bkhome.org
#License GPL3 (/usr/share/doc/legal)
#shared-mime-info pkg has assigned initrd.gz mime-type application/initramfs-gz (by me).
#Click on initrd.gz in ROX-Filer, this script will run (see /root/Choices/MIME-types/application_initramfs-gz).
#note: script not internationalized, as this is a developer's tool.
#150215 'initrd.q' cpio archive is not compressed. mime type application/initramfs[-gz]
#161212 quirky: 'easyinit' is an uncompressed cpio archive, mime type application/x-cpio. note, this script has become very clumsy.
#171016 easy os: check BOOT_SPECS if a version upgrade. need to internationalise.
#180408 handle nvme drives.
#181130 renamed 'initrd.q' to just 'initrd'. improved fixing BOOT_SPECS
#181201 Q_DISTRO* renamed to INIT_DISTRO*
#181218 fix auto-fix of BOOT_SPECS
#190104 setup infrastructure for gettext in initrd.
#190123 translate "Yes" and "No" in pupdialog. Prefix "LANG=C" before fdisk.
#190226 BOOT_SPECS now has BOOT_UUID, WKG_UUID
#190226 BOOT_SPECS in initrd no longer has INIT_LANG variable. 190304 fixes. 190309 fixes.
#190310 no longer have BOOT_PARTNUM, WKG_PARTNUM in BOOT_SPECS
#190310 make auto-fix work better. 190311 190313
#190810 fix expand quirky initrd.q

export TEXTDOMAIN=edit-initramfs
export OUTPUT_CHARSET=UTF-8
LANG1="${LANG%_*}" #190104 ex: de

. /etc/DISTRO_SPECS
. /etc/rc.d/PUPSTATE

[ ! $1 ] && exit 1
[ ! -f "$1" ] && exit 1
PARAM1="$(realpath "$1")" #181129
BASEFILE="$(basename "$PARAM1")"
DIRPATH="$(dirname "$PARAM1")" #181129
#161212 acceptable names...
BADNAME=1
case $BASEFILE in
 initrd.gz|initrd.q|easyinit) BADNAME=0 ;;
 initrd) BADNAME=0 ;;  #181129
esac
[ $BADNAME -eq 1 ] && exit 1

COMPTYPE=''; dotEXT=''
[ "${BASEFILE/*./}" == "q" ] && COMPTYPE='none' #190810 quirky initrd.q
[ "$BASEFILE" == "easyinit" ] && COMPTYPE='none' #161212

#190810 this is what get on a gz-compressed initrd.gz:
# # rox -m initrd.gz
# application/initramfs-gz
# # file ./initrd.gz 
# ./initrd.gz: gzip compressed data, was "initrd", last modified: Thu Jul 11 01:57:55 2019, from Unix
#same gz-compressed, without the .gz extension:
# # rox -m ./initrd
# application/x-gzip
# # file ./initrd
# ./initrd: gzip compressed data, was "initrd", last modified: Thu Jul 11 01:57:55 2019, from Unix

#190810 initrd.q from quirky, which is uncompressed:
# # rox -m initrd.q
# application/initramfs
# # file initrd.q
# initrd.q: ASCII cpio archive (SVR4 with no CRC)

#190810 initrd from easy, which is uncompressed:
# # rox -m initrd
# application/x-cpio
# # file initrd
# initrd: ASCII cpio archive (SVR4 with no CRC)

if which rox >/dev/null ;then #181129
 MTYPE="$(rox -m ${PARAM1})"
 [ "${MTYPE}" == "application/x-cpio" ] && COMPTYPE='none'
else
 MTYPE="$(file ${PARAM1} | grep -o 'ASCII cpio archive')"
 [ "${MTYPE}" == "ASCII cpio archive" ] && COMPTYPE='none'
fi

compr_func() {
 #find out compression type...  181129...
 if [ "$COMPTYPE" == "none" ];then
  UNCOMPREXE=''; COMPREXE=''; dotEXT='.q'
  [ "$BASEFILE" == "easyinit" ] && dotEXT='' #161212
  [ "$BASEFILE" == "initrd" ] && dotEXT=''
  return 0
 fi
 UNCOMPREXE=gunzip; COMPREXE=gzip; dotEXT='.gz'
 gunzip -t "$1"
 if [ $? -ne 0 ];then
  UNCOMPREXE=bunzip2; COMPREXE=bzip2; dotEXT='.bz2'
  bunzip2 -t "$1"
  if [ $? -ne 0 ];then
   UNCOMPREXE=unxz; COMPREXE=xz; dotEXT='.xz'
   unxz -t "$1"
   if [ $? -ne 0 ];then
    return 1
   fi
  fi
 fi
 return 0
}

#190123 yes/no buttons...
M_yes="$(gettext 'Yes')"
M_no="$(gettext 'No')"

#171016 check BOOT_SPECS  181129...
if [ ! -d initrd-expanded ];then
 if [ "$COMPTYPE" == "none" -a "$BASEFILE" == "initrd" ];then #190810 restrict to easyos initrd
  #190310 decide whether want to auto-fix...
  REASON1=""; REASON2=""
  aBOOT_DEV="$(echo -n "${PARAM1}" | cut -f 3 -d '/')" #ex: extract sdb1 from /mnt/sdb1/...
  aBOOT_DIR="$(echo -n "$DIRPATH" | cut -f 4- -d '/')" #ex: easy/0.9.9
  [ "$aBOOT_DIR" ] && aBOOT_DIR="${aBOOT_DIR}/"
  [ "${aBOOT_DIR}${aBOOT_DEV}" == "${BOOT_DIR}${BOOT_DEV}" ] && REASON1='1' #upgrading initrd that we have booted off.
  [ -f ${DIRPATH}/easy.sfs ] && REASON2='1'      #seems to be in a boot-partition.
  if [ "${REASON1}" -o "${REASON2}" ];then
   [ -d /tmp/edit-initramfs-tmp-expand ] && rm -rf /tmp/edit-initramfs-tmp-expand
   mkdir /tmp/edit-initramfs-tmp-expand
   cd /tmp/edit-initramfs-tmp-expand
   cpio -i -d -m -F ${PARAM1} #expand.
   if [ -f /tmp/edit-initramfs-tmp-expand/BOOT_SPECS ];then
    BOOT_UUID=""
. /tmp/edit-initramfs-tmp-expand/BOOT_SPECS
    
    aDRV="${aBOOT_DEV%%[1-9]}" #remove number off end.
    aBOOT_DRV="${aDRV%%[1-9]}" #repeat, in case another number on end.
    [ "$aBOOT_DRV" != "sdp" ] && aBOOT_DRV="${aBOOT_DRV%%p}" #ex: mmcblk0p becomes mmcblk0
    aBOOT_UUID="$(blkid /dev/${aBOOT_DEV} | grep -o 'UUID=.*' | cut -f 2 -d '"')"
    aBOOT_PARTNUM="${aBOOT_DEV/*[a-z]/}"
    aBOOT_FS="$(blkid /dev/${aBOOT_DEV} | tr ' ' '\n' | grep '^TYPE=' | cut -f 2 -d '"')"
    
    if [ "$REASON1" ];then
     #currently running the os that am upgrading,
     # so /etc/rc.d/PUPSTATE has the info we need here...
     aWKG_PARTNUM="${WKG_DEV/*[a-z]/}" #ex: mmcblkop1 becomes 1
     aWKG_FS="$(grep '^WKG_FS=' /etc/rc.d/PUPSTATE | cut -f 2 -d "'")"
     aWKG_DIR="$(grep '^WKG_DIR=' /etc/rc.d/PUPSTATE  | cut -f 2 -d "'")"
     aWKG_UUID="$(blkid /dev/${WKG_DEV} | grep -o 'UUID=.*' | cut -f 2 -d '"')"
     aWKG_DEV="${WKG_DEV}"
    else
     #initrd seems to be in a boot-partition.
     REASON2="" #assume fail.
     #init script should copy BOOT_SPECS to the boot-partition, makes it easier...
     if [ -f ${DIRPATH}/.BOOT_SPECS ];then
      REASON2='1'
      aWKG_DIR="$(grep '^WKG_DIR=' ${DIRPATH}/.BOOT_SPECS | cut -f 2 -d "'")"
      aWKG_UUID="$(grep '^WKG_UUID=' ${DIRPATH}/.BOOT_SPECS | cut -f 2 -d "'")"
      aWKG_DEV="$(blkid | grep "\"${aWKG_UUID}\"" | cut -f 1 -d ':' | cut -f 3 -d '/')"
     else
      #don't fail yet, check next-up partition...
      nxtPART="$((${aBOOT_PARTNUM}+1))"
      nxtDEV="${aBOOT_DRV}${nxtPART}"
      [ "${aBOOT_DRV:0:2}" == "mm" ] && nxtDEV="${aBOOT_DRV}p${nxtPART}"
      [ "${aBOOT_DRV:0:2}" == "nv" ] && nxtDEV="${aBOOT_DRV}p${nxtPART}"
      nxtFS="$(blkid /dev/${nxtDEV} | grep -o "TYPE=.*" | cut -f 2 -d '"')"
      case "$nxtFS" in
       ext*|f2fs|reiserfs)
        nxtM=0
        if ! grep "^/dev/${nxtDEV} " /proc/mounts >/dev/null;then
         mkdir -p /mnt/${nxtDEV}
         busybox mount -t ${nxtFS} /dev/${nxtDEV} /mnt/${nxtDEV}
         nxtM=1
        fi
        nxtD="/mnt/${nxtDEV}"
        nxtS="$(find /mnt/${nxtDEV} -mindepth 1 -maxdepth 1 -type d -name '.session' | head -n 1)"
        [ ! "$nxtS" ] && nxtS="$(find /mnt/${nxtDEV} -mindepth 2 -maxdepth 2 -type d -name '.session' | head -n 1)"
        [ ! "$nxtS" ] && nxtS="$(find /mnt/${nxtDEV} -mindepth 3 -maxdepth 3 -type d -name '.session' | head -n 1)"
        if [ "$nxtS" ];then
         nxtD="$(dirname "$nxtS")"
         [ -d ${nxtD}/releases ] && REASON2='1'
        else
         #if partition is empty, then that's our guy...
         nxtC=$(find ${nxtD} -mindepth 1 -maxdepth 1 -type d | wc -l)
         [ $nxtC -le 1 ] && REASON2='1'
        fi
        if [ "$REASON2" ];then
         aWKG_DIR="$(echo -n "$nxtD" | cut -f 4- -d '/')"
         [ "$aWKG_DIR" ] && aWKG_DIR="${aWKG_DIR}/"
         aWKG_UUID="$(blkid /dev/${nxtDEV} | grep -o "UUID=.*" | cut -f 2 -d '"')"
         aWKG_DEV="${nxtDEV}"
        fi
        if [ $nxtM -eq 1 ];then
         busybox umount /mnt/${nxtDEV}
        fi
       ;;
      esac
      if [ ! "$REASON2" ];then #190313
       #fallback, if aBOOT_FS a linux f.s. then assume wkg in same location...
       case "$aBOOT_FS" in
        ext*|f2fs|reiser*)
         aWKG_DIR="${aBOOT_DIR}"
         aWKG_UUID="${aBOOT_UUID}"
         aWKG_DEV="${aBOOT_DEV}"
         REASON2='1'
        ;;
       esac
      fi
     fi
    fi
    
    if [ "${REASON1}" -o "${REASON2}" ];then
     FIXflg=0
     [ "$aBOOT_UUID" != "$BOOT_UUID" ] && FIXflg=$(($FIXflg+1))
     [ "${aBOOT_DIR%/}" != "${BOOT_DIR%/}" ] && FIXflg=$(($FIXflg+1)) #remove any trailing /
     [ "$aWKG_UUID" != "$WKG_UUID" ] && FIXflg=$(($FIXflg+1))
     [ "${aWKG_DIR%/}" != "${WKG_DIR%/}" ] && FIXflg=$(($FIXflg+1)) #remove any trailing /
     [ "$BOOT_UUID" == "" ] && FIXflg=0 #precaution.
     if [ $FIXflg -gt 0 ];then
      pupdialog --yeslabel "${M_yes}" --nolabel "${M_no}" --colors --background "#ffc060" --backtitle "${BASEFILE}: $(gettext 'fix?')" --yesno "\Zb$(gettext 'The BOOT_SPECS file inside initrd may need to be fixed')\ZB

$(gettext 'If the initrd file is placed where it will be booted from, it seems that the BOOT_SPECS file is incorrect. Choose the Yes button to automatically fix it.')

$(gettext 'If you choose No, then you will be able to manually edit the BOOT_SPECS file.') \Zb\Z1$(gettext 'If you do not fully understand what is being asked here, choose No.')\Zn\ZB" 0 0
      if [ $? -eq 0 ];then
       #sed -i -e "s%^BOOT_UUID=.*%BOOT_UUID='${aBOOT_UUID}'%" /tmp/edit-initramfs-tmp-expand/BOOT_SPECS
       #sed -i -e "s%^WKG_UUID=.*%WKG_UUID='${aWKG_UUID}'%" /tmp/edit-initramfs-tmp-expand/BOOT_SPECS
       #sed -i -e "s%^BOOT_DIR=.*%BOOT_DIR='${aBOOT_DIR}'%" /tmp/edit-initramfs-tmp-expand/BOOT_SPECS
       #sed -i -e "s%^WKG_DIR=.*%WKG_DIR='${aWKG_DIR}'%" /tmp/edit-initramfs-tmp-expand/BOOT_SPECS
       echo "BOOT_UUID='${aBOOT_UUID}'
BOOT_DIR='${aBOOT_DIR}'
WKG_UUID='${aWKG_UUID}'
WKG_DIR='${aWKG_DIR}'" > /tmp/edit-initramfs-tmp-expand/BOOT_SPECS
       pupdialog --yeslabel "${M_yes}" --nolabel "${M_no}" --colors --background "#a0ffa0" --backtitle "${BASEFILE}: $(gettext 'FIXED')" --yesno "\Zb$(gettext 'The file BOOT_SPECS inside initrd has been automatically edited. This is the new content:')\ZB
 
$(cat /tmp/edit-initramfs-tmp-expand/BOOT_SPECS)

$(gettext 'Where BOOT_UUID is partition:') \Zb${aBOOT_DEV}\ZB
$(gettext '   and WKG_UUID is partition:') \Zb${aWKG_DEV}\ZB

$(gettext 'Please study this very carefully. If it is correct, click the Yes button. Otherwise, click the No button, and you may then manually edit the BOOT_SPECS file.')" 0 0
       if [ $? -eq 0 ];then
        #now put it together again...
        find . | cpio -o -H newc > ${PARAM1}
        sync
        cd /
        rm -rf /tmp/edit-initramfs-tmp-expand
        pupdialog --background '#80FF80' --backtitle "${BASEFILE}: $(gettext 'success')" --msgbox "$(gettext 'BOOT_SPECS inside this file has been updated. If you wish, you may click on it again to open it up and check the contents.')" 0 0
       else
        pupdialog --colors --background '#80FF80' --backtitle "${BASEFILE}: $(gettext 'expanded')" --msgbox "${BASEFILE} $(gettext 'has been expanded at \Zb/root/initrd-expanded\ZB. You may edit the contents if you wish. \Zb\Z1\n\nAfterward, if you click on it again\Zn\ZB, it will be updated with the contents of /root/initrd-expanded.')" 0 0
        cp -a /tmp/edit-initramfs-tmp-expand /root/initrd-expanded
        sync
        cd /
        rm -rf /tmp/edit-initramfs-tmp-expand
        rox -d /root/initrd-expanded -x /root/initrd-expanded
       fi
       exit
      fi
     fi
    fi
   fi
   cd /
   rm -rf /tmp/edit-initramfs-tmp-expand
  fi
 fi
fi

cd /root
[ -f initrd ] && rm -f initrd
[ -f initrd.q ] && rm -f initrd.q   #190810
[ -f initrd.gz ] && rm -f initrd.gz #190810

if [ -d initrd-expanded ];then
 pupdialog --yeslabel "${M_yes}" --nolabel "${M_no}" --background "yellow" --backtitle "${BASEFILE}: $(gettext 'update?')" --yesno "$(gettext 'A CPIO-archive is already expanded at /root/initrd-expanded. Is this correct, do you want to use /root/initrd-expanded to update') ${1}?" 0 0
 if [ $? -eq 0 ];then
  compr_func "$PARAM1" #sets COMPREXE, dotEXT
  if [ $? -ne 0 ];then
   pupdialog --background '#FF8080' --backtitle "${BASEFILE}: $(gettext 'fail')" --msgbox "$(gettext 'Sorry, could not recognise compression type, unable to update') ${BASEFILE}." 0 0
  else
   cd initrd-expanded
   find . | cpio -o -H newc > ../initrd
   sync
   cd ..
   if [ "$COMPREXE" ];then #190810
    ${COMPREXE} initrd
   else
    [ "$dotEXT" ] && mv -f initrd initrd${dotEXT}
   fi
   sync
   mv -f initrd${dotEXT} "$PARAM1"
   pupdialog --background '#80FF80' --backtitle "${BASEFILE}: $(gettext 'success')" --msgbox "${1} $(gettext 'has been updated with the contents of /root/initrd-expanded.')" 0 0
  fi
 fi
 pupdialog --yeslabel "${M_yes}" --nolabel "${M_no}" --background "yellow" --backtitle "${BASEFILE}: $(gettext 'finished')" --yesno "$(gettext 'Do you want to delete /root/initrd-expanded? If in doubt, please choose Yes')" 0 0
 if [ $? -eq 0 ];then
  rox -D /root/initrd-expanded 2>/dev/null
  rm -rf /root/initrd-expanded
 fi
else
 pupdialog --yeslabel "${M_yes}" --nolabel "${M_no}" --background "yellow" --backtitle "${BASEFILE}: $(gettext 'expand?')"  --yesno "${BASEFILE}: $(gettext 'Do you want to open it up, and optionally edit it?')" 0 0
 if [ $? -eq 0 ];then
  compr_func "$PARAM1" #sets UNCOMPREXE, dotEXT
  if [ $? -ne 0 ];then
   pupdialog --background '#FF8080' --backtitle "${BASEFILE}: $(gettext 'fail')" --msgbox "${BASEFILE}: $(gettext 'Sorry, could not recognise compression type, unable to expand it.')" 0 0
  else
   cp -f "$PARAM1" /root/initrd${dotEXT}
   if [ "$UNCOMPREXE" ];then #190810
    ${UNCOMPREXE} initrd${dotEXT}
   else
    [ "$dotEXT" ] && mv -f initrd${dotEXT} initrd
   fi
   mkdir initrd-expanded
   cd initrd-expanded
   cat ../initrd | cpio -i -d -m
   sync
   rm -f ../initrd
   cd ..
   pupdialog --colors --background '#80FF80' --backtitle "${BASEFILE}: $(gettext 'expanded')" --msgbox "${BASEFILE} $(gettext 'has been expanded at \Zb/root/initrd-expanded\ZB. You may edit the contents if you wish. \Zb\Z1\n\nAfterward, if you click on it again\Zn\ZB, it will be updated with the contents of /root/initrd-expanded.')" 0 0
   rox -d /root/initrd-expanded -x /root/initrd-expanded
  fi
 fi
fi

###end###
