This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade libnet from version 3.09_01 to 3.10
[perl5.git] / cpan / Digest-SHA / shasum
CommitLineData
207902b1 1#!perl
6bc89f92 2
0a178734
CBW
3 ## shasum: filter for computing SHA digests (ref. sha1sum/md5sum)
4 ##
24278fc4 5 ## Copyright (C) 2003-2015 Mark Shelor, All Rights Reserved
0a178734 6 ##
b495b81b
CBW
7 ## Version: 5.95
8 ## Sat Jan 10 12:15:36 MST 2015
65484cb9 9
207902b1
CBW
10 ## shasum SYNOPSIS adapted from GNU Coreutils sha1sum. Add
11 ## "-a" option for algorithm selection,
12 ## "-U" option for Universal Newlines support,
13 ## "-0" option for reading bit strings, and
14 ## "-p" option for portable digests (to be deprecated).
15
cee96d52 16BEGIN { pop @INC if $INC[-1] eq '.' }
207902b1
CBW
17use strict;
18use warnings;
19use Fcntl;
20use Getopt::Long;
65484cb9
CBW
21
22my $POD = <<'END_OF_POD';
6bc89f92
SP
23
24=head1 NAME
25
26shasum - Print or Check SHA Checksums
27
28=head1 SYNOPSIS
29
65484cb9 30 Usage: shasum [OPTION]... [FILE]...
6bc89f92
SP
31 Print or check SHA checksums.
32 With no FILE, or when FILE is -, read standard input.
33
65484cb9
CBW
34 -a, --algorithm 1 (default), 224, 256, 384, 512, 512224, 512256
35 -b, --binary read in binary mode
36 -c, --check read SHA sums from the FILEs and check them
9dd45029 37 -t, --text read in text mode (default)
207902b1 38 -U, --UNIVERSAL read in Universal Newlines mode
cccd5831 39 produces same digest on Windows/Unix/Mac
e39652ea
CBW
40 -0, --01 read in BITS mode
41 ASCII '0' interpreted as 0-bit,
42 ASCII '1' interpreted as 1-bit,
43 all other characters ignored
207902b1 44 -p, --portable read in portable mode (to be deprecated)
6bc89f92
SP
45
46 The following two options are useful only when verifying checksums:
65484cb9
CBW
47 -s, --status don't output anything, status code shows success
48 -w, --warn warn about improperly formatted checksum lines
49
50 -h, --help display this help and exit
51 -v, --version output version information and exit
6bc89f92 52
65484cb9
CBW
53 When verifying SHA-512/224 or SHA-512/256 checksums, indicate the
54 algorithm explicitly using the -a option, e.g.
6bc89f92 55
65484cb9 56 shasum -a 512224 -c checksumfile
6bc89f92 57
626ec6d7
AC
58 The sums are computed as described in FIPS PUB 180-4. When checking,
59 the input should be a former output of this program. The default
60 mode is to print a line with checksum, a character indicating type
207902b1
CBW
61 (`*' for binary, ` ' for text, `U' for UNIVERSAL, `^' for BITS, `?'
62 for portable), and name for each FILE.
65484cb9
CBW
63
64 Report shasum bugs to mshelor@cpan.org
6bc89f92 65
747da336
RGS
66=head1 DESCRIPTION
67
65484cb9
CBW
68Running I<shasum> is often the quickest way to compute SHA message
69digests. The user simply feeds data to the script through files or
70standard input, and then collects the results from standard output.
747da336 71
e39652ea
CBW
72The following command shows how to compute digests for typical inputs
73such as the NIST test vector "abc":
747da336 74
dfe1edcb 75 perl -e "print qq(abc)" | shasum
747da336
RGS
76
77Or, if you want to use SHA-256 instead of the default SHA-1, simply say:
78
dfe1edcb 79 perl -e "print qq(abc)" | shasum -a 256
747da336 80
65484cb9
CBW
81Since I<shasum> mimics the behavior of the combined GNU I<sha1sum>,
82I<sha224sum>, I<sha256sum>, I<sha384sum>, and I<sha512sum> programs,
747da336
RGS
83you can install this script as a convenient drop-in replacement.
84
9dd45029
A
85Unlike the GNU programs, I<shasum> encompasses the full SHA standard by
86allowing partial-byte inputs. This is accomplished through the BITS
87option (I<-0>). The following example computes the SHA-224 digest of
88the 7-bit message I<0001100>:
89
90 perl -e "print qq(0001100)" | shasum -0 -a 224
91
6bc89f92
SP
92=head1 AUTHOR
93
24278fc4 94Copyright (c) 2003-2015 Mark Shelor <mshelor@cpan.org>.
6bc89f92
SP
95
96=head1 SEE ALSO
97
65484cb9 98I<shasum> is implemented using the Perl module L<Digest::SHA> or
6bc89f92
SP
99L<Digest::SHA::PurePerl>.
100
101=cut
102
65484cb9
CBW
103END_OF_POD
104
b495b81b 105my $VERSION = "5.95";
6bc89f92 106
6bc89f92 107sub usage {
128cbdba 108 my($err, $msg) = @_;
6bc89f92 109
128cbdba
SP
110 $msg = "" unless defined $msg;
111 if ($err) {
c7e5c266 112 warn($msg . "Type shasum -h for help\n");
128cbdba
SP
113 exit($err);
114 }
626ec6d7
AC
115 my($USAGE) = $POD =~ /SYNOPSIS(.+?)^=/sm;
116 $USAGE =~ s/^\s*//;
117 $USAGE =~ s/\s*$//;
65484cb9 118 $USAGE =~ s/^ //gm;
626ec6d7 119 print $USAGE, "\n";
6bc89f92
SP
120 exit($err);
121}
122
123
0a178734
CBW
124 ## Sync stdout and stderr by forcing a flush after every write
125
65484cb9
CBW
126select((select(STDOUT), $| = 1)[0]);
127select((select(STDERR), $| = 1)[0]);
0a178734
CBW
128
129
130 ## Collect options from command line
6bc89f92
SP
131
132my ($alg, $binary, $check, $text, $status, $warn, $help, $version);
207902b1 133my ($portable, $BITS, $reverse, $UNIVERSAL, $versions);
6bc89f92 134
747da336 135eval { Getopt::Long::Configure ("bundling") };
6bc89f92 136GetOptions(
128cbdba
SP
137 'b|binary' => \$binary, 'c|check' => \$check,
138 't|text' => \$text, 'a|algorithm=i' => \$alg,
139 's|status' => \$status, 'w|warn' => \$warn,
140 'h|help' => \$help, 'v|version' => \$version,
e39652ea 141 'p|portable' => \$portable,
626ec6d7 142 '0|01' => \$BITS,
207902b1
CBW
143 'R|REVERSE' => \$reverse,
144 'U|UNIVERSAL' => \$UNIVERSAL,
626ec6d7 145 'V|VERSIONS' => \$versions,
128cbdba 146) or usage(1, "");
6bc89f92
SP
147
148
0a178734 149 ## Deal with help requests and incorrect uses
6bc89f92 150
128cbdba
SP
151usage(0)
152 if $help;
84c0b84e 153usage(1, "shasum: Ambiguous file mode\n")
207902b1
CBW
154 if scalar(grep {defined $_}
155 ($binary, $portable, $text, $BITS, $UNIVERSAL)) > 1;
c7e5c266 156usage(1, "shasum: --warn option used only when verifying checksums\n")
128cbdba 157 if $warn && !$check;
c7e5c266 158usage(1, "shasum: --status option used only when verifying checksums\n")
128cbdba 159 if $status && !$check;
6bc89f92
SP
160
161
626ec6d7
AC
162 ## Try to use Digest::SHA. If not installed, use the slower
163 ## but functionally equivalent Digest::SHA::PurePerl instead.
164
207902b1
CBW
165 ## If option -R is invoked, reverse the module preference,
166 ## i.e. try Digest::SHA::PurePerl first, then Digest::SHA.
626ec6d7 167
207902b1
CBW
168my @MODS = qw(Digest::SHA Digest::SHA::PurePerl);
169@MODS[0, 1] = @MODS[1, 0] if $reverse;
626ec6d7
AC
170
171my $module;
172for (@MODS) {
173 my $mod = $_;
174 if (eval "require $mod") {
175 $module = $mod;
176 last;
177 }
178}
179die "shasum: Unable to find " . join(" or ", @MODS) . "\n"
180 unless defined $module;
181
182
96d38a9d 183 ## Default to SHA-1 unless overridden by command line option
6bc89f92 184
dfe1edcb 185$alg = 1 unless defined $alg;
65484cb9 186grep { $_ == $alg } (1, 224, 256, 384, 512, 512224, 512256)
84c0b84e 187 or usage(1, "shasum: Unrecognized algorithm\n");
6bc89f92
SP
188
189
0a178734 190 ## Display version information if requested
6bc89f92
SP
191
192if ($version) {
193 print "$VERSION\n";
194 exit(0);
195}
196
626ec6d7
AC
197if ($versions) {
198 print "shasum $VERSION\n";
199 print "$module ", eval "\$${module}::VERSION", "\n";
200 print "perl ", defined $^V ? sprintf("%vd", $^V) : $], "\n";
201 exit(0);
202}
203
6bc89f92 204
0a178734
CBW
205 ## Try to figure out if the OS is DOS-like. If it is,
206 ## default to binary mode when reading files, unless
96d38a9d 207 ## explicitly overridden by command line "--text" or
207902b1 208 ## "--UNIVERSAL" or "--portable" options.
6bc89f92
SP
209
210my $isDOSish = ($^O =~ /^(MSWin\d\d|os2|dos|mint|cygwin)$/);
207902b1 211if ($isDOSish) { $binary = 1 unless $text || $UNIVERSAL || $portable }
128cbdba 212
207902b1
CBW
213my $modesym = $binary ? '*' : ($UNIVERSAL ? 'U' :
214 ($BITS ? '^' : ($portable ? '?' : ' ')));
6bc89f92
SP
215
216
0a178734 217 ## Read from STDIN (-) if no files listed on command line
6bc89f92
SP
218
219@ARGV = ("-") unless @ARGV;
220
221
0a178734 222 ## sumfile($file): computes SHA digest of $file
6bc89f92
SP
223
224sub sumfile {
dcbcf62d 225 my $file = shift;
6bc89f92 226
207902b1
CBW
227 my $mode = $binary ? 'b' : ($UNIVERSAL ? 'U' :
228 ($BITS ? '0' : ($portable ? 'p' : '')));
84c0b84e 229 my $digest = eval { $module->new($alg)->addfile($file, $mode) };
0a178734 230 if ($@) { warn "shasum: $file: $!\n"; return }
84c0b84e 231 $digest->hexdigest;
6bc89f92
SP
232}
233
234
0a178734 235 ## %len2alg: maps hex digest length to SHA algorithm
6bc89f92
SP
236
237my %len2alg = (40 => 1, 56 => 224, 64 => 256, 96 => 384, 128 => 512);
65484cb9
CBW
238$len2alg{56} = 512224 if $alg == 512224;
239$len2alg{64} = 512256 if $alg == 512256;
6bc89f92
SP
240
241
0a178734 242 ## unescape: convert backslashed filename to plain filename
6bc89f92 243
0a178734
CBW
244sub unescape {
245 $_ = shift;
246 s/\\\\/\0/g;
247 s/\\n/\n/g;
248 return if /\\/;
249 s/\0/\\/g;
250 return $_;
251}
6bc89f92 252
0a178734
CBW
253
254 ## verify: confirm the digest values in a checksum file
255
256sub verify {
257 my $checkfile = shift;
258 my ($err, $fmt_errs, $read_errs, $match_errs) = (0, 0, 0, 0);
65484cb9 259 my ($num_lines, $num_files) = (0, 0);
0a178734
CBW
260 my ($bslash, $sum, $fname, $rsp, $digest);
261
262 local *FH;
65484cb9 263 $checkfile eq '-' and open(FH, '< -')
9cc8ef8a
CBW
264 and $checkfile = 'standard input'
265 or sysopen(FH, $checkfile, O_RDONLY)
266 or die "shasum: $checkfile: $!\n";
0a178734
CBW
267 while (<FH>) {
268 next if /^#/; s/\n$//; s/^[ \t]+//; $num_lines++;
269 $bslash = s/^\\//;
270 ($sum, $modesym, $fname) =
207902b1 271 /^([\da-fA-F]+)[ \t]([ *?^U])([^\0]*)/;
0a178734
CBW
272 $alg = defined $sum ? $len2alg{length($sum)} : undef;
273 $fname = unescape($fname) if defined $fname && $bslash;
274 if (grep { ! defined $_ } ($alg, $sum, $modesym, $fname)) {
275 $alg = 1 unless defined $alg;
dcbcf62d 276 warn("shasum: $checkfile: $.: improperly " .
0a178734
CBW
277 "formatted SHA$alg checksum line\n") if $warn;
278 $fmt_errs++;
6bc89f92
SP
279 next;
280 }
0a178734 281 $fname =~ s/\r$// unless -e $fname;
c7e5c266 282 $rsp = "$fname: "; $num_files++;
207902b1
CBW
283 ($binary, $text, $UNIVERSAL, $BITS, $portable) =
284 map { $_ eq $modesym } ('*', ' ', 'U', '^', 'p');
747da336 285 unless ($digest = sumfile($fname)) {
dcbcf62d 286 $rsp .= "FAILED open or read\n";
c7e5c266 287 $err = 1; $read_errs++;
dcbcf62d
SP
288 }
289 else {
290 if (lc($sum) eq $digest) { $rsp .= "OK\n" }
c7e5c266 291 else { $rsp .= "FAILED\n"; $err = 1; $match_errs++ }
dcbcf62d 292 }
6bc89f92
SP
293 print $rsp unless $status;
294 }
0a178734
CBW
295 close(FH);
296 unless ($num_files) {
297 $alg = 1 unless defined $alg;
298 warn("shasum: $checkfile: no properly formatted " .
299 "SHA$alg checksum lines found\n");
300 $err = 1;
c7e5c266 301 }
0a178734
CBW
302 elsif (! $status) {
303 warn("shasum: WARNING: $fmt_errs line" . ($fmt_errs>1?
304 's are':' is') . " improperly formatted\n") if $fmt_errs;
305 warn("shasum: WARNING: $read_errs listed file" .
306 ($read_errs>1?'s':'') . " could not be read\n") if $read_errs;
307 warn("shasum: WARNING: $match_errs computed checksum" .
308 ($match_errs>1?'s':'') . " did NOT match\n") if $match_errs;
309 }
310 return($err == 0);
6bc89f92
SP
311}
312
313
0a178734 314 ## Verify or compute SHA checksums of requested files
6bc89f92 315
747da336
RGS
316my($file, $digest);
317
0a178734 318my $STATUS = 0;
747da336 319for $file (@ARGV) {
0a178734
CBW
320 if ($check) { $STATUS = 1 unless verify($file) }
321 elsif ($digest = sumfile($file)) {
322 if ($file =~ /[\n\\]/) {
323 $file =~ s/\\/\\\\/g; $file =~ s/\n/\\n/g;
324 $digest = "\\$digest";
325 }
84c0b84e 326 print "$digest $modesym", "$file\n";
6bc89f92 327 }
0a178734 328 else { $STATUS = 1 }
6bc89f92 329}
0a178734 330exit($STATUS)