Add Digest-SHA-5.32 for SHA-256 support for CPAN.
[p5sagit/p5-mst-13.2.git] / ext / Digest / SHA / bin / shasum
1 #!perl -w
2
3         # shasum: filter for computing SHA digests (analogous to md5sum)
4         #
5         # Copyright (C) 2003-2005 Mark Shelor, All Rights Reserved
6         #
7         # Version: 5.32
8         # Fri Dec  2 02:32:20 MST 2005
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
24   -t, --text         read files in text mode (default)
25
26  The following two options are useful only when verifying checksums:
27
28       --status       don't output anything, status code shows success
29   -w, --warn         warn about improperly formatted SHA checksum lines
30
31       --help         display this help and exit
32       --version      output version information and exit
33
34 The sums are computed as described in FIPS PUB 180-2.  When checking,
35 the input should be a former output of this program.  The default
36 mode is to print a line with checksum, a character indicating type
37 (`*' for binary, ` ' for text), and name for each FILE.
38
39 =head1 AUTHOR
40
41 Copyright (c) 2003-2005 Mark Shelor <mshelor@cpan.org>.
42
43 =head1 SEE ALSO
44
45 Shasum is implemented using the Perl module L<Digest::SHA> or
46 L<Digest::SHA::PurePerl>.
47
48 =cut
49
50 use strict;
51 use Getopt::Long;
52
53 my $VERSION = "5.32";
54
55
56         # Try to use Digest::SHA, since it's faster.  If not installed,
57         # use Digest::SHA::PurePerl instead.
58
59 my $MOD_PREFER = "Digest::SHA";
60 my $MOD_SECOND = "Digest::SHA::PurePerl";
61
62 my $module = $MOD_PREFER;
63 eval "require $module";
64 if ($@) {
65         $module = $MOD_SECOND;
66         eval "require $module";
67         die "Unable to find $MOD_PREFER or $MOD_SECOND\n" if $@;
68 }
69
70
71         # Usage statement adapted from Ulrich Drepper's md5sum.
72         # Include an "-a" option for algorithm selection.
73
74 sub usage {
75         my($err) = @_;
76
77         my $stream = $err ? *STDERR : *STDOUT;
78         print $stream <<'END_OF_USAGE';
79 Usage: shasum [OPTION] [FILE]...
80    or: shasum [OPTION] --check [FILE]
81 Print or check SHA checksums.
82 With no FILE, or when FILE is -, read standard input.
83
84   -a, --algorithm    1 (default), 224, 256, 384, 512
85   -b, --binary       read files in binary mode (default on DOS/Windows)
86   -c, --check        check SHA sums against given list
87   -t, --text         read files in text mode (default)
88
89 The following two options are useful only when verifying checksums:
90       --status       don't output anything, status code shows success
91   -w, --warn         warn about improperly formatted SHA checksum lines
92
93       --help         display this help and exit
94       --version      output version information and exit
95
96 The sums are computed as described in FIPS PUB 180-2.  When checking,
97 the input should be a former output of this program.  The default
98 mode is to print a line with checksum, a character indicating type
99 (`*' for binary, ` ' for text), and name for each FILE.
100
101 Report bugs to <mshelor@cpan.org>.
102 END_OF_USAGE
103         exit($err);
104 }
105
106
107         # Collect options from command line
108
109 my ($alg, $binary, $check, $text, $status, $warn, $help, $version);
110
111 GetOptions(
112         'binary' => \$binary, 'check' => \$check,
113         'text' => \$text, 'algorithm=i' => \$alg,
114         'status' => \$status, 'warn' => \$warn,
115         'help' => \$help, 'version' => \$version
116 ) or usage(1);
117
118
119         # Deal with help requests and incorrect uses
120
121 usage(0) if $help;
122 usage(1) if $binary and $text;
123 usage(1) if $warn and not $check;
124 usage(1) if $status and not $check;
125
126
127         # Default to SHA-1 unless overriden by command line option
128
129 $alg = 1 unless $alg;
130 grep { $_ == $alg } (1, 224, 256, 384, 512) or usage(1);
131
132
133         # Display version information if requested
134
135 if ($version) {
136         print "$VERSION\n";
137         exit(0);
138 }
139
140
141         # Try to figure out if the OS is DOS-like.  If it is,
142         # default to binary mode when reading files, unless
143         # explicitly overriden by command line "text" option.
144
145 my $isDOSish = ($^O =~ /^(MSWin\d\d|os2|dos|mint|cygwin)$/);
146 if ($isDOSish) { $binary = 1 unless $text }
147
148
149         # Read from STDIN (-) if no files listed on command line
150
151 @ARGV = ("-") unless @ARGV;
152
153
154         # sumfile($file): computes SHA digest of $file
155
156 sub sumfile {
157         my($file) = @_;
158         my($fh, $digest);
159
160         unless (open($fh, "<$file")) {
161                 print STDERR "shasum: $file: No such file or directory\n";
162                 return;
163         }
164         binmode($fh) if $binary;
165         $digest = $module->new($alg)->addfile($fh)->hexdigest;
166         close($fh);
167         return($digest);
168 }
169
170
171         # %len2alg: maps hex digest length to SHA algorithm
172
173 my %len2alg = (40 => 1, 56 => 224, 64 => 256, 96 => 384, 128 => 512);
174
175
176         # Verify checksums if requested
177
178 if ($check) {
179         my $checkfile = shift(@ARGV);
180         my $err = 0;
181         my ($fh, $sum, $fname, $rsp);
182
183         die "shasum: $checkfile: No such file or directory\n"
184                 unless open($fh, "<$checkfile");
185         while (<$fh>) {
186                 s/\s+$//;
187                 ($sum, $binary, $fname) = /^(\S+)\s+(\*?)(.*)$/;
188                 unless ($alg = $len2alg{length($sum)}) {
189                         print STDERR "shasum: $checkfile: $.: improperly ",
190                                 "formatted SHA checksum line\n" if $warn;
191                         next;
192                 }
193                 $rsp = "$fname: ";
194                 if (lc($sum) eq sumfile($fname)) { $rsp .= "OK\n" }
195                 else { $rsp .= "FAILED\n"; $err = 1 }
196                 print $rsp unless $status;
197         }
198         close($fh);
199         exit($err);
200 }
201
202
203         # Compute and display SHA checksums of requested files
204
205 for (@ARGV) {
206         if (-d $_) {
207                 print STDERR "shasum: $_: Is a directory\n";
208                 next;
209         }
210         next unless my $digest = sumfile($_);
211         print "$digest ", $binary ? "\*" : " ", "$_\n";
212 }