#!/bin/sh # Verify a file's SHA-256 against an expected hex digest, on any host. # # tools/sha256check.sh # # There is no one checksum command across the supported hosts. Linux and Git # Bash have coreutils' sha256sum; macOS ships shasum(1) and no sha256sum; # FreeBSD and NetBSD ship sha256(1) with a different output format again; # OpenBSD has sha256 too but usually reached through cksum -a sha256. A recipe # that hardcodes any one of them builds on some of the hosts this project # supports and fails on the rest, and the failure arrives only when someone # first runs `make ports` on a Mac. # # Compares digests rather than trusting a -c flag, because the -c input format # differs between the implementations as well. set -eu if [ $# -ne 2 ]; then echo "usage: $0 " >&2 exit 2 fi expected="$1" file="$2" if [ ! -f "$file" ]; then echo "sha256check: no such file: $file" >&2 exit 1 fi actual= if command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$file" | cut -d' ' -f1) elif command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$file" | cut -d' ' -f1) elif command -v sha256 >/dev/null 2>&1; then # FreeBSD/NetBSD: -q prints the digest alone. actual=$(sha256 -q "$file") elif command -v cksum >/dev/null 2>&1 && cksum -a sha256 /dev/null >/dev/null 2>&1; then # OpenBSD. actual=$(cksum -a sha256 "$file" | sed 's/.*= *//') elif command -v openssl >/dev/null 2>&1; then actual=$(openssl dgst -sha256 "$file" | sed 's/.*= *//') else echo "sha256check: no usable checksum tool found" >&2 echo " looked for: sha256sum, shasum, sha256, cksum, openssl" >&2 exit 1 fi # Case-insensitive: openssl and sha256 have been known to differ here. expected_lc=$(printf '%s' "$expected" | tr 'A-Z' 'a-z') actual_lc=$(printf '%s' "$actual" | tr 'A-Z' 'a-z') if [ "$expected_lc" != "$actual_lc" ]; then echo "sha256check: checksum mismatch for $file" >&2 echo " expected: $expected_lc" >&2 echo " actual: $actual_lc" >&2 exit 1 fi echo "$file: OK"