pkgsrc/mk/checksum/checksum
2006-12-15 13:15:06 +00:00

187 lines
5.1 KiB
Bash
Executable file

#!/bin/sh
#
# $NetBSD: checksum,v 1.10 2006/12/15 13:15:06 martti Exp $
#
# Copyright (c) 2006 The NetBSD Foundation, Inc.
# All rights reserved.
#
# This code is derived from software contributed to The NetBSD Foundation
# by Johnny C. Lam.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
######################################################################
#
# NAME
# checksum -- checksum files
#
# SYNOPSIS
# checksum [options] distinfo [file ...]
#
# DESCRIPTION
# checksum will verify the checksums in the distinfo file for each
# of the files specified.
#
# OPTIONS
# -a algorithm Only verify checksums for the specified algorithm.
# -s suffix Strip the specified suffix from the file names
# when searching for the checksum.
#
######################################################################
set -e # exit on errors
: ${DIGEST:=digest}
: ${CAT:=cat}
: ${ECHO:=echo}
: ${TEST:=test}
self="${0##*/}"
usage() {
${ECHO} 1>&2 "usage: $self [-a algorithm] [-s suffix] distinfo [file ...]"
}
# Process optional arguments
algorithm=
suffix=
while ${TEST} $# -gt 0; do
case "$1" in
-a) algorithm="$2"; shift 2 ;;
-s) suffix="$2"; shift 2 ;;
--) shift; break ;;
-*) ${ECHO} 1>&2 "$self: unknown option -- ${1#-}"
usage
exit 1
;;
*) break ;;
esac
done
# Process required arguments
${TEST} $# -gt 0 || { usage; exit 1; }
distinfo="$1"; shift
files="$@"
if ${TEST} ! -f "$distinfo"; then
${ECHO} 1>&2 "$self: distinfo file missing: $distinfo"
exit 1
fi
digestcmd=
case "${DIGEST}" in
/*)
if ${TEST} -x "${DIGEST}"; then
digestcmd="${DIGEST}"
fi
;;
*)
SAVEIFS="$IFS"; IFS=:
for i in $PATH; do
if ${TEST} -x "$i/${DIGEST}"; then
digestcmd="$i/${DIGEST}"
break
fi
done
IFS="$SAVEIFS"
;;
esac
if ${TEST} -z "$digestcmd"; then
${ECHO} 1>&2 "$self: \`\`${DIGEST}'' is missing"
exit 1
fi
{ exitcode=0
while read d_alg d_file d_equals d_checksum; do
case "$d_alg" in
"#"*) continue ;; # skip comments
"\$"*) continue ;; # skip RCS ID
"") continue ;; # skip empty lines
Size) continue ;; # skip lines holding filesizes, not checksums
esac
if ${TEST} -n "$algorithm"; then
${TEST} "$d_alg" = "$algorithm" || continue
fi
eval "tmp=\"\$_alg_${d_alg}\""
${TEST} -n "$tmp" || eval "_alg_${d_alg}=\"$files\""
for file in $files; do
sfile="${file%$suffix}"
${TEST} "$d_file" = "($sfile)" || continue
eval "tmp=\"\$_alg_${d_alg}\""
case "$tmp" in
"$file"|"$file "*) tmp_pre= ;;
*" $file") tmp_pre="${tmp%% $file}" ;;
*) tmp_pre="${tmp%% $file *} " ;;
esac
case "$tmp" in
"$file"|*" $file") tmp_post= ;;
"$file "*) tmp_post="${tmp##$file }" ;;
*) tmp_post="${tmp##* $file }" ;;
esac
tmp="${tmp_pre}${tmp_post}"
eval "_alg_${d_alg}=\"$tmp\""
if ${TEST} "$d_checksum" = "IGNORE"; then
${ECHO} 1>&2 "$self: Ignoring checksum for $sfile"
continue
fi
if ${TEST} ! -f $file; then
${ECHO} 1>&2 "$self: $file does not exist"
exit 1
fi
checksum=`${DIGEST} $d_alg < $file`
if ${TEST} "$d_checksum" = "$checksum"; then
${ECHO} "=> Checksum $d_alg OK for $sfile"
else
${ECHO} 1>&2 "$self: Checksum $d_alg mismatch for $sfile"
exitcode=1
fi
break
done
eval "tmp=\"\$_alg_${d_alg}\""
${TEST} -n "$tmp" || eval "_alg_${d_alg}=DONE"
done
if ${TEST} -n "$algorithm"; then
eval "tmp=\"\$_alg_${algorithm}\""
${TEST} -n "$tmp" || tmp="$files"
if ${TEST} "$tmp" != DONE; then
for file in $tmp; do
${ECHO} 1>&2 "$self: No $algorithm checksum recorded for $file"
exitcode=1
done
fi
fi
exit $exitcode; } < $distinfo