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