#!/bin/sh
#
# mkimage.sh - DF-2655 full image construction (run as root in the guest).
#
#   1. fresh 2GB image, newfs_hammer2
#   2. mount via vn; create zdir (comp=zlib:6) with a 128KB compressible
#      zfile, and lzdir (default comp=lz4) with a 128KB lzfile
#   3. clean unmount; save pristine copies (image + file contents)
#   4. h2zsub dump + patch: imgA=zfile lbase-0 ZLIB payload -> zlib-invalid
#      (0xFF); imgB=lzfile lbase-0 LZ4 stream -> decompress-fail.
#      ALL integrity checks (XXH64 chain + volhdr iCRC32) are fixed up so
#      the kernel considers the metadata (and the corrupted payload's
#      checksum) fully valid.
#
# usage: ./mkimage.sh [workdir]   (default /root/df2655)
set -e
D=${1:-/root/df2655}
cd "$D"

gen_pattern() {
	# 32-byte recognizable line repeated to $1 bytes (compressible,
	# non-zero)
	n=$(($1 / 32))
	i=0
	while [ $i -lt $n ]; do
		printf "DF2655-SUBSTITUTION-%07d\n" $i
		i=$((i + 1))
	done
}

echo "=== [1/5] fresh images + newfs_hammer2"
rm -f h2base.img h2z.img h2z.pristine.img h2l.img h2l.pristine.img
truncate -s 2G h2base.img
newfs_hammer2 h2base.img > mkfs.log 2>&1
grep -E 'PFS|Volume' mkfs.log || true

echo "=== [2/5] mount, populate, clean unmount"
VNU=$(vnconfig -c vn "$D/h2base.img")
echo "clone unit: $VNU"
mount_hammer2 /dev/$VNU@LOCAL /mnt
mkdir /mnt/zdir
hammer2 setcomp zlib:6 /mnt/zdir
gen_pattern 131072 > /mnt/zdir/zfile
mkdir /mnt/lzdir
gen_pattern 131072 > /mnt/lzdir/lzfile
sync
ls -l /mnt/zdir /mnt/lzdir
cp /mnt/zdir/zfile "$D/zfile.orig"
cp /mnt/lzdir/lzfile "$D/lzfile.orig"
md5 "$D/zfile.orig" "$D/lzfile.orig" | tee content.md5
cd "$D"
umount /mnt
umount /mnt 2>/dev/null || true
vnconfig -d "$VNU" 2>/dev/null || true
# keep the populated base pristine, then fork per-test images
cp h2base.img h2z.pristine.img
cp h2base.img h2z.img
cp h2base.img h2l.pristine.img
cp h2base.img h2l.img

echo "=== [3/5] dump pristine topology (per file)"
./h2zsub h2z.pristine.img dump > dump.pristine.log 2>&1
grep -E 'inode "|DATA ' dump.pristine.log

echo "=== [4/5] patch imgA (zfile, ZLIB payload -> zlib-invalid)"
./h2zsub h2z.img patch zfile zlib 0 2>&1 | tee patch.zlib.log
./h2zsub h2z.img dump > dump.patched-zlib.log 2>&1
grep -A2 'DATA  lbase=0000000000000000' dump.patched-zlib.log | head -4

echo "=== [5/5] patch imgB (lzfile, LZ4 stream -> decompress-fail, small)"
./h2zsub h2l.img patch lzfile lz4 0 2>&1 | tee patch.lz4.log
./h2zsub h2l.img dump > dump.patched-lz4.log 2>&1
grep -A2 'DATA  lbase=0000000000000000' dump.patched-lz4.log | head -4

echo "mkimage done."
