#!/bin/bash
# This script helps core_dumper annotate the end of compressed core files with additional data,
# including EOS version and a list of packaging change since boot; the latter reflects installed
# patches, extensions, etc for better debugging.
#
# This script is called with a single argument reflecting the current calling context:
#
#   boot     - boot time; get the initial package list; called by daemoh at startup
#   gen      - generate new annotation if needed and cache.
#   annotate - regen annotation if needed and output to stdout; called from core_dumper
#   daemon   - using inotifywait, wait for changes to rpm database and update annotation when seen;
#              called via systemd CoreUtil.service.

annoDir=/var/tmp/core_annotation
pkgsAtBoot=${annoDir}/pkgsAtBoot
pkgsNow=${annoDir}/pkgsNow
annotation=${annoDir}/annotation
tmpfile=${annoDir}/tmp.$$

oldPkgDb=/var/lib/rpm/Packages
newPkgDb=/var/lib/rpm/rpmdb.sqlite

pkgDbDir=/var/lib/rpm
arg=${1:-"annotate"}
export PATH=/usr/bin:$PATH

# repeated bit of code that returns 0 if annotation is up to date.
upToDate() {
    local pkgDb
    [ -e "${oldPkgDb}" ] && pkgDb="${oldPkgDb}" || pkgDb="${newPkgDb}"
    [ -e ${annotation} ] && [ -e ${pkgDb} ] && [ ${annotation} -nt ${pkgDb} ] 
}
# generate package list, sorted in C locale
genPackages() {
    rpm -qa | LC_ALL="C" sort 
}

# record list of packages; run from CoreUtil.service prerun script.
if [ "$arg" = "boot" ] ; then
    mkdir -p ${annoDir}
    rm ${annotation}
    genPackages > ${pkgsAtBoot}    
    exit 0
fi

                                                       
# (re)generate json annotation file
if [ "$arg" = "gen" ]; then
    # reversed logic lets us test by modifying pkg files and invoking 'gen'
    # directly
    if ! upToDate; then
        # generate list of currently installed packages
        genPackages > ${pkgsNow}    
    fi
    
    # get cmd to report swi version info
    if [ -f /etc/swi-version ]; then
        # we're on a switch
        cmd="cat /etc/swi-version"
    elif [ -f /images/EOS.swi ]; then
        # we're in a workspace
        cmd='swi info /images/EOS.swi'
    else
        # Abuild is pretty sparse....
        cmd='printf SWI_VERSION=unknown\nSWI_ARCH=bogus\nSWI_RELEASE=fake\nSERIALNUM=0'        
    fi
    # Generate new annotation file in json format.
    ( ${cmd} ; diff ${pkgsAtBoot} ${pkgsNow} ) | python3 -c '
from CoreAnnotation import pkgDiffsToJSON
pkgDiffsToJSON()
' >  $tmpfile
    mv ${tmpfile} ${annotation} # atomic replace.
fi

# output (and update if needed) annotation file to stdout
if [ "$arg" = "annotate" ]; then
    if ! upToDate; then
        $0 gen
    fi    
    cat ${annotation}
fi

# daemon that updates annotation file when pkgs are changed;
# run from CoreUtil.service
if [ "$arg" = "daemon" ]; then
    # loop, updating annotation whenever we see rpms updated
    while true; do
        if ! upToDate; then
            $0 gen
        fi
        inotifywait -e modify ${pkgDbDir}
    done
fi
