Commit | Line | Data |
---|---|---|
6bc89f92 SP |
1 | #!perl -w |
2 | ||
84c0b84e | 3 | # shasum: filter for computing SHA digests (analogous to sha1sum) |
6bc89f92 | 4 | # |
dfe1edcb | 5 | # Copyright (C) 2003-2010 Mark Shelor, All Rights Reserved |
6bc89f92 | 6 | # |
dfe1edcb CBW |
7 | # Version: 5.48 |
8 | # Mon Jan 4 16:32:52 MST 2010 | |
6bc89f92 SP |
9 | |
10 | =head1 NAME | |
11 | ||
12 | shasum - Print or Check SHA Checksums | |
13 | ||
14 | =head1 SYNOPSIS | |
15 | ||
16 | Usage: shasum [OPTION] [FILE]... | |
17 | or: shasum [OPTION] --check [FILE] | |
18 | Print or check SHA checksums. | |
19 | With no FILE, or when FILE is -, read standard input. | |
20 | ||
21 | -a, --algorithm 1 (default), 224, 256, 384, 512 | |
22 | -b, --binary read files in binary mode (default on DOS/Windows) | |
23 | -c, --check check SHA sums against given list | |
128cbdba | 24 | -p, --portable read files in portable mode |
cccd5831 | 25 | produces same digest on Windows/Unix/Mac |
6bc89f92 SP |
26 | -t, --text read files in text mode (default) |
27 | ||
28 | The following two options are useful only when verifying checksums: | |
29 | ||
128cbdba | 30 | -s, --status don't output anything, status code shows success |
6bc89f92 SP |
31 | -w, --warn warn about improperly formatted SHA checksum lines |
32 | ||
128cbdba SP |
33 | -h, --help display this help and exit |
34 | -v, --version output version information and exit | |
6bc89f92 | 35 | |
128cbdba SP |
36 | The sums are computed as described in FIPS PUB 180-2. When checking, |
37 | the input should be a former output of this program. The default mode | |
38 | is to print a line with checksum, a character indicating type (`*' | |
39 | for binary, `?' for portable, ` ' for text), and name for each FILE. | |
6bc89f92 | 40 | |
747da336 RGS |
41 | =head1 DESCRIPTION |
42 | ||
43 | The I<shasum> script provides the easiest and most convenient way to | |
44 | compute SHA message digests. Rather than writing a program, the user | |
45 | simply feeds data to the script via the command line, and waits for | |
46 | the results to be printed on standard output. Data can be fed to | |
47 | I<shasum> through files, standard input, or both. | |
48 | ||
49 | The following command shows how easy it is to compute digests for typical | |
50 | inputs such as the NIST test vector "abc": | |
51 | ||
dfe1edcb | 52 | perl -e "print qq(abc)" | shasum |
747da336 RGS |
53 | |
54 | Or, if you want to use SHA-256 instead of the default SHA-1, simply say: | |
55 | ||
dfe1edcb | 56 | perl -e "print qq(abc)" | shasum -a 256 |
747da336 RGS |
57 | |
58 | Since I<shasum> uses the same interface employed by the familiar | |
59 | I<sha1sum> program (and its somewhat outmoded anscestor I<md5sum>), | |
60 | you can install this script as a convenient drop-in replacement. | |
61 | ||
6bc89f92 SP |
62 | =head1 AUTHOR |
63 | ||
dfe1edcb | 64 | Copyright (c) 2003-2010 Mark Shelor <mshelor@cpan.org>. |
6bc89f92 SP |
65 | |
66 | =head1 SEE ALSO | |
67 | ||
128cbdba | 68 | shasum is implemented using the Perl module L<Digest::SHA> or |
6bc89f92 SP |
69 | L<Digest::SHA::PurePerl>. |
70 | ||
71 | =cut | |
72 | ||
73 | use strict; | |
747da336 | 74 | use FileHandle; |
6bc89f92 SP |
75 | use Getopt::Long; |
76 | ||
dfe1edcb | 77 | my $VERSION = "5.48"; |
6bc89f92 SP |
78 | |
79 | ||
80 | # Try to use Digest::SHA, since it's faster. If not installed, | |
81 | # use Digest::SHA::PurePerl instead. | |
82 | ||
83 | my $MOD_PREFER = "Digest::SHA"; | |
84 | my $MOD_SECOND = "Digest::SHA::PurePerl"; | |
85 | ||
86 | my $module = $MOD_PREFER; | |
747da336 | 87 | eval "require $module"; |
6bc89f92 SP |
88 | if ($@) { |
89 | $module = $MOD_SECOND; | |
747da336 | 90 | eval "require $module"; |
6bc89f92 SP |
91 | die "Unable to find $MOD_PREFER or $MOD_SECOND\n" if $@; |
92 | } | |
93 | ||
94 | ||
95 | # Usage statement adapted from Ulrich Drepper's md5sum. | |
128cbdba SP |
96 | # Include an "-a" option for algorithm selection, |
97 | # and a "-p" option for portable digest computation. | |
6bc89f92 SP |
98 | |
99 | sub usage { | |
128cbdba | 100 | my($err, $msg) = @_; |
6bc89f92 | 101 | |
128cbdba SP |
102 | $msg = "" unless defined $msg; |
103 | if ($err) { | |
c7e5c266 | 104 | warn($msg . "Type shasum -h for help\n"); |
128cbdba SP |
105 | exit($err); |
106 | } | |
c7e5c266 | 107 | print <<'END_OF_USAGE'; |
6bc89f92 SP |
108 | Usage: shasum [OPTION] [FILE]... |
109 | or: shasum [OPTION] --check [FILE] | |
110 | Print or check SHA checksums. | |
111 | With no FILE, or when FILE is -, read standard input. | |
112 | ||
113 | -a, --algorithm 1 (default), 224, 256, 384, 512 | |
114 | -b, --binary read files in binary mode (default on DOS/Windows) | |
115 | -c, --check check SHA sums against given list | |
128cbdba | 116 | -p, --portable read files in portable mode |
cccd5831 | 117 | produces same digest on Windows/Unix/Mac |
6bc89f92 SP |
118 | -t, --text read files in text mode (default) |
119 | ||
120 | The following two options are useful only when verifying checksums: | |
128cbdba | 121 | -s, --status don't output anything, status code shows success |
6bc89f92 SP |
122 | -w, --warn warn about improperly formatted SHA checksum lines |
123 | ||
128cbdba SP |
124 | -h, --help display this help and exit |
125 | -v, --version output version information and exit | |
6bc89f92 | 126 | |
128cbdba SP |
127 | The sums are computed as described in FIPS PUB 180-2. When checking, the |
128 | input should be a former output of this program. The default mode is to | |
129 | print a line with checksum, a character indicating type (`*' for binary, | |
130 | `?' for portable, ` ' for text), and name for each FILE. | |
6bc89f92 SP |
131 | |
132 | Report bugs to <mshelor@cpan.org>. | |
133 | END_OF_USAGE | |
134 | exit($err); | |
135 | } | |
136 | ||
137 | ||
138 | # Collect options from command line | |
139 | ||
140 | my ($alg, $binary, $check, $text, $status, $warn, $help, $version); | |
128cbdba | 141 | my ($portable); |
6bc89f92 | 142 | |
747da336 | 143 | eval { Getopt::Long::Configure ("bundling") }; |
6bc89f92 | 144 | GetOptions( |
128cbdba SP |
145 | 'b|binary' => \$binary, 'c|check' => \$check, |
146 | 't|text' => \$text, 'a|algorithm=i' => \$alg, | |
147 | 's|status' => \$status, 'w|warn' => \$warn, | |
148 | 'h|help' => \$help, 'v|version' => \$version, | |
149 | 'p|portable' => \$portable | |
150 | ) or usage(1, ""); | |
6bc89f92 SP |
151 | |
152 | ||
153 | # Deal with help requests and incorrect uses | |
154 | ||
128cbdba SP |
155 | usage(0) |
156 | if $help; | |
84c0b84e | 157 | usage(1, "shasum: Ambiguous file mode\n") |
128cbdba | 158 | if scalar(grep { defined $_ } ($binary, $portable, $text)) > 1; |
c7e5c266 | 159 | usage(1, "shasum: --warn option used only when verifying checksums\n") |
128cbdba | 160 | if $warn && !$check; |
c7e5c266 | 161 | usage(1, "shasum: --status option used only when verifying checksums\n") |
128cbdba | 162 | if $status && !$check; |
6bc89f92 SP |
163 | |
164 | ||
165 | # Default to SHA-1 unless overriden by command line option | |
166 | ||
dfe1edcb | 167 | $alg = 1 unless defined $alg; |
128cbdba | 168 | grep { $_ == $alg } (1, 224, 256, 384, 512) |
84c0b84e | 169 | or usage(1, "shasum: Unrecognized algorithm\n"); |
6bc89f92 SP |
170 | |
171 | ||
172 | # Display version information if requested | |
173 | ||
174 | if ($version) { | |
175 | print "$VERSION\n"; | |
176 | exit(0); | |
177 | } | |
178 | ||
179 | ||
180 | # Try to figure out if the OS is DOS-like. If it is, | |
181 | # default to binary mode when reading files, unless | |
c7e5c266 SP |
182 | # explicitly overriden by command line "--text" or |
183 | # "--portable" options. | |
6bc89f92 SP |
184 | |
185 | my $isDOSish = ($^O =~ /^(MSWin\d\d|os2|dos|mint|cygwin)$/); | |
128cbdba SP |
186 | if ($isDOSish) { $binary = 1 unless $text || $portable } |
187 | ||
c7e5c266 | 188 | my $modesym = $binary ? '*' : ($portable ? '?' : ' '); |
6bc89f92 SP |
189 | |
190 | ||
191 | # Read from STDIN (-) if no files listed on command line | |
192 | ||
193 | @ARGV = ("-") unless @ARGV; | |
194 | ||
195 | ||
196 | # sumfile($file): computes SHA digest of $file | |
197 | ||
198 | sub sumfile { | |
dcbcf62d | 199 | my $file = shift; |
6bc89f92 | 200 | |
84c0b84e SP |
201 | my $mode = $portable ? 'p' : ($binary ? 'b' : ''); |
202 | my $digest = eval { $module->new($alg)->addfile($file, $mode) }; | |
203 | if ($@) { | |
204 | warn "shasum: $file: $!\n"; | |
c7e5c266 SP |
205 | return; |
206 | } | |
c7e5c266 | 207 | |
84c0b84e | 208 | $digest->hexdigest; |
6bc89f92 SP |
209 | } |
210 | ||
211 | ||
212 | # %len2alg: maps hex digest length to SHA algorithm | |
213 | ||
214 | my %len2alg = (40 => 1, 56 => 224, 64 => 256, 96 => 384, 128 => 512); | |
215 | ||
216 | ||
217 | # Verify checksums if requested | |
218 | ||
219 | if ($check) { | |
220 | my $checkfile = shift(@ARGV); | |
c7e5c266 SP |
221 | my ($err, $read_errs, $match_errs) = (0, 0, 0); |
222 | my ($num_files, $num_checksums) = (0, 0); | |
747da336 | 223 | my ($fh, $sum, $fname, $rsp, $digest); |
6bc89f92 | 224 | |
84c0b84e | 225 | die "shasum: $checkfile: $!\n" |
747da336 | 226 | unless $fh = FileHandle->new($checkfile, "r"); |
6bc89f92 SP |
227 | while (<$fh>) { |
228 | s/\s+$//; | |
c7e5c266 | 229 | ($sum, $modesym, $fname) = /^(\S+) (.)(.*)$/; |
128cbdba | 230 | ($binary, $portable, $text) = |
c7e5c266 | 231 | map { $_ eq $modesym } ('*', '?', ' '); |
6bc89f92 | 232 | unless ($alg = $len2alg{length($sum)}) { |
dcbcf62d SP |
233 | warn("shasum: $checkfile: $.: improperly " . |
234 | "formatted SHA checksum line\n") if $warn; | |
6bc89f92 SP |
235 | next; |
236 | } | |
c7e5c266 | 237 | $rsp = "$fname: "; $num_files++; |
747da336 | 238 | unless ($digest = sumfile($fname)) { |
dcbcf62d | 239 | $rsp .= "FAILED open or read\n"; |
c7e5c266 | 240 | $err = 1; $read_errs++; |
dcbcf62d SP |
241 | } |
242 | else { | |
c7e5c266 | 243 | $num_checksums++; |
dcbcf62d | 244 | if (lc($sum) eq $digest) { $rsp .= "OK\n" } |
c7e5c266 | 245 | else { $rsp .= "FAILED\n"; $err = 1; $match_errs++ } |
dcbcf62d | 246 | } |
6bc89f92 SP |
247 | print $rsp unless $status; |
248 | } | |
747da336 | 249 | $fh->close; |
c7e5c266 SP |
250 | unless ($status) { |
251 | warn("shasum: WARNING: $read_errs of $num_files listed " . | |
252 | "files could not be read\n") if $read_errs; | |
253 | warn("shasum: WARNING: $match_errs of $num_checksums " . | |
254 | "computed checksums did NOT match\n") if $match_errs; | |
255 | } | |
6bc89f92 SP |
256 | exit($err); |
257 | } | |
258 | ||
259 | ||
260 | # Compute and display SHA checksums of requested files | |
261 | ||
747da336 RGS |
262 | my($file, $digest); |
263 | ||
264 | for $file (@ARGV) { | |
265 | if ($digest = sumfile($file)) { | |
84c0b84e | 266 | print "$digest $modesym", "$file\n"; |
6bc89f92 | 267 | } |
6bc89f92 | 268 | } |