-
Notifications
You must be signed in to change notification settings - Fork 4
/
csum
executable file
·144 lines (113 loc) · 3.17 KB
/
csum
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/bin/bash
# version 1.1
set -euo pipefail
run() {
echo>&2 "+ $*"
"$@"
}
usage() {
cat >&2 <<EOM
usage: $(basename "$0") FILE...
Check a checksum file and associated gnupg signatures.
For each checksum FILE listed, verify the GnuPG signature from FILE.gpg, then
determine what hash (md5, sha1, sha2) algorithm it uses, and check all of the
checksums of the listed files.
Hashes of missing files will be silently skipped (using --ignore-missing).
This is especially useful for verifying the SHA256SUMS, SHA256SUMS.gpg files
that accompany software downloads.
For example:
csum SHA256SUMS
EOM
}
if [ $# -eq 0 ]; then
usage
exit 1
fi
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
usage
exit
fi
colorecho() {
color="$1"
shift
if [ ! -t 1 ]; then
echo "$*"
return
fi
case "$color" in
black|gray|grey) fg=30 ;;
red) fg=31 ;;
green) fg=32 ;;
yellow) fg=33 ;;
blue) fg=34 ;;
magenta|purple|violet) fg=35 ;;
cyan) fg=36 ;;
white) fg=37 ;;
*)
echo >&2 "colorecho: unknown color: $color"
return 1
;;
esac
echo -ne "\033[1;${fg}m"
echo -n "$*"
echo -e "\033[m"
}
errx() {
code=$1
shift
colorecho red "$(basename "$0"): $*" >&2
exit "$code"
}
warn() {
colorecho yellow "$(basename "$0"): $*" >&2
}
delayerr=
for file in "$@"; do
if [ -r "$file" ] && [ ! -s "$file" ]; then
errx 2 "'$file' is empty"
fi
# Read file until first space character
# This should be a hexadecimal checksum
read -r -d ' ' first_hash < "$file" && ret=$? || ret=$?
hashlen=${#first_hash}
if [ "$ret" -ne 0 ]; then
errx "$ret" "read '$file' exited with error status $ret"
fi
# Bail out if we see chars other than hexadecimal
if ! [[ $first_hash =~ ^[a-fA-F0-9]+$ ]]; then
colorecho red "Are you sure this is a checksum file?"
errx 3 "'$file' has unexpected chars where hex checksum should be"
fi
# Guess hash algorithm based on length of digest
case $hashlen in
32) cmd=md5sum ;;
40) cmd=sha1sum ;;
56) cmd=sha224sum ;;
64) cmd=sha256sum ;;
98) cmd=sha384sum ;;
128) cmd=sha512sum ;;
*)
colorecho red "Are you sure this is a checksum file?"
errx 3 "'$file' has unexpected hash length $hashlen"
;;
esac
if [ -r "$file.sig" ]; then
run gpg --verify "$file.sig" "$file"
elif [ -r "$file.asc" ]; then
run gpg --verify "$file.asc" "$file"
elif [ -r "$file.gpg" ]; then
run gpg --verify "$file.gpg" "$file"
elif [ -r "$file.sign" ]; then
run gpg --verify "$file.sign" "$file"
else
warn "Warning: no signature found at $file.{asc,gpg,sig,sign}"
delayerr=5
fi
run "$cmd" -c --strict --ignore-missing "$file" && ret=$? || ret=$?
if [ "$ret" -ne 0 ]; then
errx "$ret" "$cmd exited with error status $ret"
fi
done
if [ -n "$delayerr" ]; then
exit "$delayerr"
fi