This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade to Digest-SHA-5.44.
[perl5.git] / ext / Digest / SHA / bin / shasum
CommitLineData
6bc89f92
SP
1#!perl -w
2
84c0b84e 3 # shasum: filter for computing SHA digests (analogous to sha1sum)
6bc89f92 4 #
77d2a621 5 # Copyright (C) 2003-2006 Mark Shelor, All Rights Reserved
6bc89f92 6 #
1bd6a86e
SP
7 # Version: 5.44
8 # Sat Oct 14 00:42:44 MST 2006
6bc89f92
SP
9
10=head1 NAME
11
12shasum - 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
SP
40
41=head1 AUTHOR
42
77d2a621 43Copyright (c) 2003-2006 Mark Shelor <mshelor@cpan.org>.
6bc89f92
SP
44
45=head1 SEE ALSO
46
128cbdba 47shasum is implemented using the Perl module L<Digest::SHA> or
6bc89f92
SP
48L<Digest::SHA::PurePerl>.
49
50=cut
51
52use strict;
53use Getopt::Long;
54
1bd6a86e 55my $VERSION = "5.44";
6bc89f92
SP
56
57
58 # Try to use Digest::SHA, since it's faster. If not installed,
59 # use Digest::SHA::PurePerl instead.
60
61my $MOD_PREFER = "Digest::SHA";
62my $MOD_SECOND = "Digest::SHA::PurePerl";
63
64my $module = $MOD_PREFER;
cccd5831 65eval "require $module"; ## no critic
6bc89f92
SP
66if ($@) {
67 $module = $MOD_SECOND;
cccd5831 68 eval "require $module"; ## no critic
6bc89f92
SP
69 die "Unable to find $MOD_PREFER or $MOD_SECOND\n" if $@;
70}
71
72
73 # Usage statement adapted from Ulrich Drepper's md5sum.
128cbdba
SP
74 # Include an "-a" option for algorithm selection,
75 # and a "-p" option for portable digest computation.
6bc89f92
SP
76
77sub usage {
128cbdba 78 my($err, $msg) = @_;
6bc89f92 79
128cbdba
SP
80 $msg = "" unless defined $msg;
81 if ($err) {
c7e5c266 82 warn($msg . "Type shasum -h for help\n");
128cbdba
SP
83 exit($err);
84 }
c7e5c266 85 print <<'END_OF_USAGE';
6bc89f92
SP
86Usage: shasum [OPTION] [FILE]...
87 or: shasum [OPTION] --check [FILE]
88Print or check SHA checksums.
89With no FILE, or when FILE is -, read standard input.
90
91 -a, --algorithm 1 (default), 224, 256, 384, 512
92 -b, --binary read files in binary mode (default on DOS/Windows)
93 -c, --check check SHA sums against given list
128cbdba 94 -p, --portable read files in portable mode
cccd5831 95 produces same digest on Windows/Unix/Mac
6bc89f92
SP
96 -t, --text read files in text mode (default)
97
98The following two options are useful only when verifying checksums:
128cbdba 99 -s, --status don't output anything, status code shows success
6bc89f92
SP
100 -w, --warn warn about improperly formatted SHA checksum lines
101
128cbdba
SP
102 -h, --help display this help and exit
103 -v, --version output version information and exit
6bc89f92 104
128cbdba
SP
105The sums are computed as described in FIPS PUB 180-2. When checking, the
106input should be a former output of this program. The default mode is to
107print a line with checksum, a character indicating type (`*' for binary,
108`?' for portable, ` ' for text), and name for each FILE.
6bc89f92
SP
109
110Report bugs to <mshelor@cpan.org>.
111END_OF_USAGE
112 exit($err);
113}
114
115
116 # Collect options from command line
117
118my ($alg, $binary, $check, $text, $status, $warn, $help, $version);
128cbdba 119my ($portable);
6bc89f92 120
128cbdba 121Getopt::Long::Configure ("bundling");
6bc89f92 122GetOptions(
128cbdba
SP
123 'b|binary' => \$binary, 'c|check' => \$check,
124 't|text' => \$text, 'a|algorithm=i' => \$alg,
125 's|status' => \$status, 'w|warn' => \$warn,
126 'h|help' => \$help, 'v|version' => \$version,
127 'p|portable' => \$portable
128) or usage(1, "");
6bc89f92
SP
129
130
131 # Deal with help requests and incorrect uses
132
128cbdba
SP
133usage(0)
134 if $help;
84c0b84e 135usage(1, "shasum: Ambiguous file mode\n")
128cbdba 136 if scalar(grep { defined $_ } ($binary, $portable, $text)) > 1;
c7e5c266 137usage(1, "shasum: --warn option used only when verifying checksums\n")
128cbdba 138 if $warn && !$check;
c7e5c266 139usage(1, "shasum: --status option used only when verifying checksums\n")
128cbdba 140 if $status && !$check;
6bc89f92
SP
141
142
143 # Default to SHA-1 unless overriden by command line option
144
145$alg = 1 unless $alg;
128cbdba 146grep { $_ == $alg } (1, 224, 256, 384, 512)
84c0b84e 147 or usage(1, "shasum: Unrecognized algorithm\n");
6bc89f92
SP
148
149
150 # Display version information if requested
151
152if ($version) {
153 print "$VERSION\n";
154 exit(0);
155}
156
157
158 # Try to figure out if the OS is DOS-like. If it is,
159 # default to binary mode when reading files, unless
c7e5c266
SP
160 # explicitly overriden by command line "--text" or
161 # "--portable" options.
6bc89f92
SP
162
163my $isDOSish = ($^O =~ /^(MSWin\d\d|os2|dos|mint|cygwin)$/);
128cbdba
SP
164if ($isDOSish) { $binary = 1 unless $text || $portable }
165
c7e5c266 166my $modesym = $binary ? '*' : ($portable ? '?' : ' ');
6bc89f92
SP
167
168
169 # Read from STDIN (-) if no files listed on command line
170
171@ARGV = ("-") unless @ARGV;
172
173
174 # sumfile($file): computes SHA digest of $file
175
176sub sumfile {
dcbcf62d 177 my $file = shift;
6bc89f92 178
84c0b84e
SP
179 my $mode = $portable ? 'p' : ($binary ? 'b' : '');
180 my $digest = eval { $module->new($alg)->addfile($file, $mode) };
181 if ($@) {
182 warn "shasum: $file: $!\n";
c7e5c266
SP
183 return;
184 }
c7e5c266 185
84c0b84e 186 $digest->hexdigest;
6bc89f92
SP
187}
188
189
190 # %len2alg: maps hex digest length to SHA algorithm
191
192my %len2alg = (40 => 1, 56 => 224, 64 => 256, 96 => 384, 128 => 512);
193
194
195 # Verify checksums if requested
196
197if ($check) {
198 my $checkfile = shift(@ARGV);
c7e5c266
SP
199 my ($err, $read_errs, $match_errs) = (0, 0, 0);
200 my ($num_files, $num_checksums) = (0, 0);
6bc89f92
SP
201 my ($fh, $sum, $fname, $rsp);
202
84c0b84e 203 die "shasum: $checkfile: $!\n"
44e8b72c 204 unless open($fh, "<$checkfile"); ## no critic
6bc89f92
SP
205 while (<$fh>) {
206 s/\s+$//;
c7e5c266 207 ($sum, $modesym, $fname) = /^(\S+) (.)(.*)$/;
128cbdba 208 ($binary, $portable, $text) =
c7e5c266 209 map { $_ eq $modesym } ('*', '?', ' ');
6bc89f92 210 unless ($alg = $len2alg{length($sum)}) {
dcbcf62d
SP
211 warn("shasum: $checkfile: $.: improperly " .
212 "formatted SHA checksum line\n") if $warn;
6bc89f92
SP
213 next;
214 }
c7e5c266 215 $rsp = "$fname: "; $num_files++;
dcbcf62d
SP
216 unless (my $digest = sumfile($fname)) {
217 $rsp .= "FAILED open or read\n";
c7e5c266 218 $err = 1; $read_errs++;
dcbcf62d
SP
219 }
220 else {
c7e5c266 221 $num_checksums++;
dcbcf62d 222 if (lc($sum) eq $digest) { $rsp .= "OK\n" }
c7e5c266 223 else { $rsp .= "FAILED\n"; $err = 1; $match_errs++ }
dcbcf62d 224 }
6bc89f92
SP
225 print $rsp unless $status;
226 }
227 close($fh);
c7e5c266
SP
228 unless ($status) {
229 warn("shasum: WARNING: $read_errs of $num_files listed " .
230 "files could not be read\n") if $read_errs;
231 warn("shasum: WARNING: $match_errs of $num_checksums " .
232 "computed checksums did NOT match\n") if $match_errs;
233 }
6bc89f92
SP
234 exit($err);
235}
236
237
238 # Compute and display SHA checksums of requested files
239
84c0b84e
SP
240for my $file (@ARGV) {
241 if (my $digest = sumfile($file)) {
242 print "$digest $modesym", "$file\n";
6bc89f92 243 }
6bc89f92 244}