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