#!/bin/sh
set -eu

script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
output_dir=${1:?usage: prepare_error_fixtures.sh OUTPUT-DIRECTORY}

for tool in mkfs.erofs dump.erofs fsck.erofs python3; do
	command -v "$tool" >/dev/null 2>&1 || {
		echo "missing tool: $tool" >&2
		exit 1
	}
done
test ! -e "$output_dir" || {
	echo "output already exists: $output_dir" >&2
	exit 1
}

work_dir=$(mktemp -d "${TMPDIR:-/tmp}/repo22-errors.XXXXXX")
trap 'rm -rf "$work_dir"' EXIT HUP INT TERM
source_dir="$work_dir/source"
mkdir -p "$source_dir"

printf 'directory entry target\n' > "$source_dir/bad-entry.txt"
printf 'inode format target\n' > "$source_dir/inode-target.txt"
printf 'high offset data path\n' > "$source_dir/high-offset.txt"
printf 'control file\n' > "$source_dir/control.txt"
dd if=/dev/zero of="$source_dir/plain.bin" bs=1048576 count=2 status=none
awk 'BEGIN { for (i = 0; i < 131072; i++)
    printf "%08d deterministic compressed payload\n", i }' \
	> "$source_dir/compressed.bin"
find "$source_dir" -exec touch -h -t 197001010000.00 {} +

mkfs.erofs --quiet -d0 -x-1 -T0 --all-time --all-root --workers=1 \
	-U 33333333-4444-5555-6666-777777777771 \
	-E noinline_data,force-inode-extended \
	"$work_dir/plain.erofs" "$source_dir"
mkfs.erofs --quiet -d0 -x-1 -T0 --all-time --all-root --workers=1 \
	-U 33333333-4444-5555-6666-777777777772 \
	-E legacy-compress,force-inode-extended -zlz4 -C65536 \
	"$work_dir/lz4.erofs" "$source_dir"
mkfs.erofs --quiet -d0 -x-1 -T0 --all-time --all-root --workers=1 \
	-U 33333333-4444-5555-6666-777777777773 \
	-E legacy-compress,force-inode-extended -zdeflate,level=1 -C65536 \
	"$work_dir/deflate.erofs" "$source_dir"

dump.erofs --path=/compressed.bin -e "$work_dir/lz4.erofs" \
	> "$work_dir/compressed.extents"
set -- $(awk '/^[[:space:]]*0:/ {
    gsub(/\.\./, "", $7); print $7, $NF; exit
}' "$work_dir/compressed.extents")
test "$#" -eq 2 || {
	echo "could not parse first compressed extent" >&2
	exit 1
}
compressed_offset=$1
compressed_length=$2

python3 "$script_dir/erofs_fixture.py" make-error-fixtures \
	--plain "$work_dir/plain.erofs" \
	--compressed "$work_dir/lz4.erofs" \
	--deflate "$work_dir/deflate.erofs" \
	--compressed-offset "$compressed_offset" \
	--compressed-length "$compressed_length" \
	--output "$output_dir"
cp -R "$source_dir" "$output_dir/source"
cp "$work_dir/compressed.extents" "$output_dir/compressed.extents"

extract_dir="$work_dir/extract-control"
mkdir "$extract_dir"
fsck.erofs --extract="$extract_dir" "$output_dir/valid-lz4.erofs"
cmp "$source_dir/compressed.bin" "$extract_dir/compressed.bin"
mkdir "$work_dir/extract-deflate"
fsck.erofs --extract="$work_dir/extract-deflate" \
	"$output_dir/valid-deflate-level1.erofs"
cmp "$source_dir/compressed.bin" "$work_dir/extract-deflate/compressed.bin"
mkdir "$work_dir/extract-corrupt"
set +e
fsck.erofs --extract="$work_dir/extract-corrupt" \
	"$output_dir/compressed-stream-corrupt.erofs" \
	> "$output_dir/compressed-corrupt-fsck.txt" 2>&1
fsck_status=$?
set -e
test "$fsck_status" -ne 0 || {
	echo "corrupted compressed stream unexpectedly extracted" >&2
	exit 1
}
printf 'compressed_corrupt_fsck_status=%s\n' "$fsck_status" \
	>> "$output_dir/fixture-evidence.txt"
cat "$output_dir/fixture-evidence.txt"
cat "$output_dir/SHA256SUMS"
