#!/bin/sh

# Copyright (C) 2019 Assaf Gordon (assafgordon@gmail.com)
# Placed under public domain
#
# a sha256sum-like program that acts like a unix filter program.
# see: https://lists.gnu.org/archive/html/coreutils/2019-05/msg00026.html
#
# Usage example:
#     $ echo "hello world" > 1.txt
#     $ sha256sum 1.txt
#     8cd07f3a5ff98f2a78cfc366c13fb123eb8d29c1ca37c79df190425d5b9e424d  1.txt
#
#   Test with incorrect checksum:
#     $ cat 1.txt | ./sha256filter.sh 8cd07f3a5ff98f2a78cfc366c13fb123eb8d29c1ca37c79df190425d99999999 | wc -l
#     sha256filter.sh: error: input does not match expected checksum
#     0
#
#   With correct checksum:
#     $ cat 1.txt | ./sha256filter.sh 8cd07f3a5ff98f2a78cfc366c13fb123eb8d29c1ca37c79df190425d5b9e424d | wc -l
#     1

die()
{
  base=$(basename "$0")
  echo "$base: error: $*" >&2
  exit 1
}

expected="$1"
test -z "$1" && die "missing sha256 checksum string"
printf "%s" "$1" | grep -q -E '^[0-9A-Fa-f]{64}$' \
  || die "invalid sha256 checksum string ($1)"

if test -f /dev/stdin ; then
  # regular file

  # duplicate STDIN file handle
  # fd 3 will be used to calculate checksum.
  # fd 4 will be used to print the output (its file-offset will be 0, as
  # if the input file was lseek'd to the beginning).
  exec 3</dev/stdin
  exec 4</dev/stdin

else

  ## not a regular file (pipe/socket/etc) - buffering required
  tmpfile=$(mktemp -p /dev/shm -t sha256filter.XXXXXX) \
    || die "mktemp in /dev/shm failed"

  cat /dev/stdin > "$tmpfile" \
    || die "failed to read data into /dev/shm buffer"

  # duplicate file handle to keep it open
  exec 3<"$tmpfile"
  exec 4<"$tmpfile"

  rm "$tmpfile"
fi

sum=$(sha256sum <&3) || die "sha256sum failed"
sum=$(printf "%s\n" "$sum" | cut -d " " -f1)

test "$sum" = "$expected" || die "input does not match expected checksum"

cat <&4 || die "cat failed"
