3 eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'
4 if 0; # not running under some shell
6 # shasum: filter for computing SHA digests (analogous to sha1sum)
8 # Copyright (C) 2003-2010 Mark Shelor, All Rights Reserved
11 # Mon Jan 4 16:32:52 MST 2010
15 shasum - Print or Check SHA Checksums
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.
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)
31 The following two options are useful only when verifying checksums:
33 -s, --status don't output anything, status code shows success
34 -w, --warn warn about improperly formatted SHA checksum lines
36 -h, --help display this help and exit
37 -v, --version output version information and exit
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.
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.
52 The following command shows how easy it is to compute digests for typical
53 inputs such as the NIST test vector "abc":
55 perl -e "print qq(abc)" | shasum
57 Or, if you want to use SHA-256 instead of the default SHA-1, simply say:
59 perl -e "print qq(abc)" | shasum -a 256
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.
67 Copyright (c) 2003-2010 Mark Shelor <mshelor@cpan.org>.
71 shasum is implemented using the Perl module L<Digest::SHA> or
72 L<Digest::SHA::PurePerl>.
83 # Try to use Digest::SHA, since it's faster. If not installed,
84 # use Digest::SHA::PurePerl instead.
86 my $MOD_PREFER = "Digest::SHA";
87 my $MOD_SECOND = "Digest::SHA::PurePerl";
89 my $module = $MOD_PREFER;
90 eval "require $module";
92 $module = $MOD_SECOND;
93 eval "require $module";
94 die "Unable to find $MOD_PREFER or $MOD_SECOND\n" if $@;
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.
105 $msg = "" unless defined $msg;
107 warn($msg . "Type shasum -h for help\n");
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.
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)
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
127 -h, --help display this help and exit
128 -v, --version output version information and exit
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.
135 Report bugs to <mshelor@cpan.org>.
141 # Collect options from command line
143 my ($alg, $binary, $check, $text, $status, $warn, $help, $version);
146 eval { Getopt::Long::Configure ("bundling") };
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
156 # Deal with help requests and incorrect uses
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")
164 usage(1, "shasum: --status option used only when verifying checksums\n")
165 if $status && !$check;
168 # Default to SHA-1 unless overriden by command line option
170 $alg = 1 unless defined $alg;
171 grep { $_ == $alg } (1, 224, 256, 384, 512)
172 or usage(1, "shasum: Unrecognized algorithm\n");
175 # Display version information if requested
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.
188 my $isDOSish = ($^O =~ /^(MSWin\d\d|os2|dos|mint|cygwin)$/);
189 if ($isDOSish) { $binary = 1 unless $text || $portable }
191 my $modesym = $binary ? '*' : ($portable ? '?' : ' ');
194 # Read from STDIN (-) if no files listed on command line
196 @ARGV = ("-") unless @ARGV;
199 # sumfile($file): computes SHA digest of $file
204 my $mode = $portable ? 'p' : ($binary ? 'b' : '');
205 my $digest = eval { $module->new($alg)->addfile($file, $mode) };
207 warn "shasum: $file: $!\n";
215 # %len2alg: maps hex digest length to SHA algorithm
217 my %len2alg = (40 => 1, 56 => 224, 64 => 256, 96 => 384, 128 => 512);
220 # Verify checksums if requested
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);
228 die "shasum: $checkfile: $!\n"
229 unless $fh = FileHandle->new($checkfile, "r");
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;
240 $rsp = "$fname: "; $num_files++;
241 unless ($digest = sumfile($fname)) {
242 $rsp .= "FAILED open or read\n";
243 $err = 1; $read_errs++;
247 if (lc($sum) eq $digest) { $rsp .= "OK\n" }
248 else { $rsp .= "FAILED\n"; $err = 1; $match_errs++ }
250 print $rsp 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;
263 # Compute and display SHA checksums of requested files
268 if ($digest = sumfile($file)) {
269 print "$digest $modesym", "$file\n";