#!/bin/bash
# The compiled helpers in rpi-image-gen-host exist because Debian's own
# builds will not do. Assert the specific capability each is here for, not
# its mere presence: an archive copy dropped in its place must fail this.
set -uo pipefail

HOSTBIN=/usr/lib/rpi-image-gen/host/bin
GENIMAGE_VERSION=20
fail=0

cd "${AUTOPKGTEST_TMP:-$(mktemp -d)}" || exit 1

# genimage and mkfs.erofs are both reached for by bare name, so host/bin has
# to be ahead of /usr/bin on the PATH patch 0006 builds. It does not have to
# be first outright - tools.sh puts the workroot directories ahead of it,
# deliberately - so the prepend itself is what to look for.
echo "== lib/tools.sh prepends host/bin to the PATH rpi-image-gen builds"
if grep -q 'PATH="/usr/lib/rpi-image-gen/host/bin:\${PATH}"' \
      /usr/share/rpi-image-gen/lib/tools.sh 2>/dev/null ; then
   echo "   ok"
else
   echo "   FAIL: no host/bin prepend found in lib/tools.sh"
   fail=1
fi

echo "== the tools that prepend exists for are in ${HOSTBIN}"
for t in genimage mkfs.erofs ; do
   if [[ -x ${HOSTBIN}/$t ]] ; then
      echo "   ok ($t)"
   else
      echo "   FAIL: ${HOSTBIN}/$t missing or not executable"
      fail=1
   fi
done

# Pinned newer than Debian's, which lacks the verity handlers the OTA image
# layouts use. Checking the version rather than -x keeps an archive genimage
# symlinked into place from passing.
echo "== genimage is the vendored ${GENIMAGE_VERSION} build"
got=$("${HOSTBIN}"/genimage --version 2>&1 | head -1)
if [[ $got == "$GENIMAGE_VERSION" ]] ; then
   echo "   ok ($got)"
else
   echo "   FAIL: genimage reports '${got}', expected ${GENIMAGE_VERSION}"
   fail=1
fi

# The reason erofs-utils is vendored at all. A 2712 device runs a 16K page
# size kernel; layer/rpi/device/arm64/linux-image-2712 forces page_size to
# 16384 and the ab_userdata layout passes it to mkfs.erofs as -b. Debian's
# erofs-utils is built without MAX_BLOCK_SIZE, inherits the 4K page size of
# the buildd, and answers "<E> erofs: invalid block size 16384".
echo "== mkfs.erofs accepts the 16K block size a 2712 rootfs needs"
mkdir -p src && echo content > src/file || { echo "   FAIL: no scratch dir"; exit 1; }
for b in 4096 16384 ; do
   if "${HOSTBIN}"/mkfs.erofs -b "$b" -z zstd,3 "img-$b.erofs" src \
         > "mkfs-$b.log" 2>&1 ; then
      echo "   ok (-b $b)"
   else
      echo "   FAIL (-b $b)"
      sed 's/^/   | /' "mkfs-$b.log"
      fail=1
   fi
done

# Vendoring narrows nothing a user could already reach for: fs_erofs_mkfs_args
# is a documented variable, and the archive binary is the baseline anyone will
# have compared against. Each of these is conditional on a configure option in
# lib/compressor.c, so each can go missing; plain "deflate" is not listed, as
# it is erofs's built-in encoder and registers unconditionally. libdeflate is
# the one that matters most - its configure default is "no", so it is the one
# a lost flag silently drops.
echo "== mkfs.erofs offers the compressors Debian's own build does"
avail=$("${HOSTBIN}"/mkfs.erofs -V 2>&1 | sed -n 's/^available compressors: //p')
for z in lz4 lzma libdeflate zstd ; do
   if [[ ,${avail// /}, == *,"$z",* ]] ; then
      echo "   ok ($z)"
   else
      echo "   FAIL: $z missing (have: ${avail:-none})"
      fail=1
   fi
done

# The checks above call each tool directly. This one does not: genimage
# reaches mkfs.erofs by bare name (image-erofs.c, get_opt("mkfserofs")), so
# driving genimage off a host/bin-prepended PATH covers the pair working
# together, and covers the block size surviving into the superblock rather
# than merely being accepted on the command line. Debian's mkfs.erofs cannot
# produce this image at all, so a pass also says which binary the PATH chose.
echo "== genimage drives mkfs.erofs, and 16K reaches the superblock"
gi=$PWD/genimage
mkdir -p "$gi"/root/etc "$gi"/input "$gi"/images "$gi"/tmp || exit 1
echo rpi-image-gen > "$gi/root/etc/marker"
cat > "$gi/genimage.cfg" <<'EOF'
image root.erofs {
   erofs {
      extraargs = "-b 16384 -z zstd,3"
   }
}
EOF
if ( cd "$gi" && PATH="${HOSTBIN}:${PATH}" genimage --config genimage.cfg \
        --rootpath root --inputpath input --outputpath images --tmppath tmp ) \
      > "$gi/genimage.log" 2>&1 ; then
   img=$gi/images/root.erofs
   # erofs_super_block sits at offset 1024: magic at +0, blkszbits at +12.
   # A byte at a time, because erofs stores the magic little-endian and od's
   # multi-byte formats interpret in host order - -tx4 would only compare
   # equal on a little-endian builder, and this package is Architecture: any.
   magic=$(od -An -tx1 -j1024 -N4 "$img" 2>/dev/null | tr -d ' \n')
   bits=$(od -An -tu1 -j1036 -N1 "$img" 2>/dev/null | tr -d ' ')
   if [[ $magic == e2e1f5e0 && $bits == 14 ]] ; then
      echo "   ok (erofs superblock, blkszbits=$bits -> $((1 << bits)) bytes)"
   else
      echo "   FAIL: magic bytes ${magic:-none} blkszbits=${bits:-none}," \
           "wanted e2e1f5e0 and 14"
      fail=1
   fi
else
   echo "   FAIL: genimage run failed"
   sed 's/^/   | /' "$gi/genimage.log"
   fail=1
fi

exit $fail
