This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update Digest-SHA to CPAN version 5.97
[perl5.git] / cpan / Digest-SHA / shasum
index 344e8e1..59c3839 100644 (file)
@@ -1,15 +1,24 @@
-#!perl -w
+#!perl
 
        ## shasum: filter for computing SHA digests (ref. sha1sum/md5sum)
        ##
-       ## Copyright (C) 2003-2011 Mark Shelor, All Rights Reserved
+       ## Copyright (C) 2003-2017 Mark Shelor, All Rights Reserved
        ##
-       ## Version: 5.70
-       ## Wed Dec 14 02:32:10 MST 2011
+       ## Version: 5.97
+       ## Wed Sep  6 02:23:02 MST 2017
 
-       ## shasum SYNOPSIS adapted from GNU Coreutils sha1sum.
-       ## Include an "-a" option for algorithm selection, and a
-       ## "-p" option for portable digest computation.
+       ## shasum SYNOPSIS adapted from GNU Coreutils sha1sum. Add
+       ## "-a" option for algorithm selection,
+       ## "-U" option for Universal Newlines support,
+       ## "-0" option for reading bit strings, and
+       ## "-p" option for portable digests (to be deprecated).
+
+BEGIN { pop @INC if $INC[-1] eq '.' }
+
+use strict;
+use warnings;
+use Fcntl;
+use Getopt::Long;
 
 my $POD = <<'END_OF_POD';
 
@@ -26,16 +35,18 @@ shasum - Print or Check SHA Checksums
    -a, --algorithm   1 (default), 224, 256, 384, 512, 512224, 512256
    -b, --binary      read in binary mode
    -c, --check       read SHA sums from the FILEs and check them
-   -p, --portable    read in portable mode
+   -t, --text        read in text mode (default)
+   -U, --UNIVERSAL   read in Universal Newlines mode
                          produces same digest on Windows/Unix/Mac
    -0, --01          read in BITS mode
                          ASCII '0' interpreted as 0-bit,
                          ASCII '1' interpreted as 1-bit,
                          all other characters ignored
-   -t, --text        read in text mode (default)
+   -p, --portable    read in portable mode (to be deprecated)
 
- The following two options are useful only when verifying checksums:
+ The following three options are useful only when verifying checksums:
    -s, --status      don't output anything, status code shows success
+   -q, --quiet       don't print OK for each successfully verified file
    -w, --warn        warn about improperly formatted checksum lines
 
    -h, --help        display this help and exit
@@ -46,10 +57,14 @@ shasum - Print or Check SHA Checksums
 
    shasum -a 512224 -c checksumfile
 
- The sums are computed as described in FIPS-180-4.  When checking, the
- input should be a former output of this program.  The default mode is to
- print a line with checksum, a character indicating type (`*' for binary,
- ` ' for text, `?' for portable, `^' for BITS), and name for each FILE.
+ The sums are computed as described in FIPS PUB 180-4.  When checking,
+ the input should be a former output of this program.  The default
+ mode is to print a line with checksum, a character indicating type
+ (`*' for binary, ` ' for text, `U' for UNIVERSAL, `^' for BITS, `?'
+ for portable), and name for each FILE.  The line starts with a `\'
+ character if the FILE name contains either newlines or backslashes,
+ which are then replaced by the two-character sequences `\n' and `\\'
+ respectively.
 
  Report shasum bugs to mshelor@cpan.org
 
@@ -72,9 +87,16 @@ Since I<shasum> mimics the behavior of the combined GNU I<sha1sum>,
 I<sha224sum>, I<sha256sum>, I<sha384sum>, and I<sha512sum> programs,
 you can install this script as a convenient drop-in replacement.
 
+Unlike the GNU programs, I<shasum> encompasses the full SHA standard by
+allowing partial-byte inputs.  This is accomplished through the BITS
+option (I<-0>).  The following example computes the SHA-224 digest of
+the 7-bit message I<0001100>:
+
+       perl -e "print qq(0001100)" | shasum -0 -a 224
+
 =head1 AUTHOR
 
-Copyright (c) 2003-2011 Mark Shelor <mshelor@cpan.org>.
+Copyright (c) 2003-2017 Mark Shelor <mshelor@cpan.org>.
 
 =head1 SEE ALSO
 
@@ -85,27 +107,7 @@ L<Digest::SHA::PurePerl>.
 
 END_OF_POD
 
-use strict;
-use Fcntl;
-use Getopt::Long;
-
-my $VERSION = "5.70";
-
-
-       ## Try to use Digest::SHA.  If not installed, use the slower
-       ## but functionally equivalent Digest::SHA::PurePerl instead.
-
-my $MOD_PREFER = "Digest::SHA";
-my $MOD_SECOND = "Digest::SHA::PurePerl";
-
-my $module = $MOD_PREFER;
-eval "require $module";
-if ($@) {
-       $module = $MOD_SECOND;
-       eval "require $module";
-       die "Unable to find $MOD_PREFER or $MOD_SECOND\n" if $@;
-}
-
+my $VERSION = "5.97";
 
 sub usage {
        my($err, $msg) = @_;
@@ -115,9 +117,11 @@ sub usage {
                warn($msg . "Type shasum -h for help\n");
                exit($err);
        }
-       my($USAGE) = $POD =~ /SYNOPSIS\n\n(.+)\n=head1 DESCRIPTION\n/sm;
+       my($USAGE) = $POD =~ /SYNOPSIS(.+?)^=/sm;
+       $USAGE =~ s/^\s*//;
+       $USAGE =~ s/\s*$//;
        $USAGE =~ s/^ //gm;
-       print $USAGE;
+       print $USAGE, "\n";
        exit($err);
 }
 
@@ -130,17 +134,21 @@ select((select(STDERR), $| = 1)[0]);
 
        ## Collect options from command line
 
-my ($alg, $binary, $check, $text, $status, $warn, $help, $version);
-my ($portable, $BITS);
+my ($alg, $binary, $check, $text, $status, $quiet, $warn, $help, $version);
+my ($portable, $BITS, $reverse, $UNIVERSAL, $versions);
 
 eval { Getopt::Long::Configure ("bundling") };
 GetOptions(
        'b|binary' => \$binary, 'c|check' => \$check,
        't|text' => \$text, 'a|algorithm=i' => \$alg,
        's|status' => \$status, 'w|warn' => \$warn,
+       'q|quiet' => \$quiet,
        'h|help' => \$help, 'v|version' => \$version,
        'p|portable' => \$portable,
-       '0|01' => \$BITS
+       '0|01' => \$BITS,
+       'R|REVERSE' => \$reverse,
+       'U|UNIVERSAL' => \$UNIVERSAL,
+       'V|VERSIONS' => \$versions,
 ) or usage(1, "");
 
 
@@ -149,14 +157,38 @@ GetOptions(
 usage(0)
        if $help;
 usage(1, "shasum: Ambiguous file mode\n")
-       if scalar(grep {defined $_} ($binary, $portable, $text, $BITS)) > 1;
+       if scalar(grep {defined $_}
+               ($binary, $portable, $text, $BITS, $UNIVERSAL)) > 1;
 usage(1, "shasum: --warn option used only when verifying checksums\n")
        if $warn && !$check;
 usage(1, "shasum: --status option used only when verifying checksums\n")
        if $status && !$check;
+usage(1, "shasum: --quiet option used only when verifying checksums\n")
+       if $quiet && !$check;
+
+
+       ## Try to use Digest::SHA.  If not installed, use the slower
+       ## but functionally equivalent Digest::SHA::PurePerl instead.
 
+       ## If option -R is invoked, reverse the module preference,
+       ## i.e. try Digest::SHA::PurePerl first, then Digest::SHA.
 
-       ## Default to SHA-1 unless overriden by command line option
+my @MODS = qw(Digest::SHA Digest::SHA::PurePerl);
+@MODS[0, 1] = @MODS[1, 0] if $reverse;
+
+my $module;
+for (@MODS) {
+       my $mod = $_;
+       if (eval "require $mod") {
+               $module = $mod;
+               last;
+       }
+}
+die "shasum: Unable to find " . join(" or ", @MODS) . "\n"
+       unless defined $module;
+
+
+       ## Default to SHA-1 unless overridden by command line option
 
 $alg = 1 unless defined $alg;
 grep { $_ == $alg } (1, 224, 256, 384, 512, 512224, 512256)
@@ -170,16 +202,24 @@ if ($version) {
        exit(0);
 }
 
+if ($versions) {
+       print "shasum $VERSION\n";
+       print "$module ", eval "\$${module}::VERSION", "\n";
+       print "perl ", defined $^V ? sprintf("%vd", $^V) : $], "\n";
+       exit(0);
+}
+
 
        ## Try to figure out if the OS is DOS-like.  If it is,
        ## default to binary mode when reading files, unless
-       ## explicitly overriden by command line "--text" or
-       ## "--portable" options.
+       ## explicitly overridden by command line "--text" or
+       ## "--UNIVERSAL" or "--portable" options.
 
 my $isDOSish = ($^O =~ /^(MSWin\d\d|os2|dos|mint|cygwin)$/);
-if ($isDOSish) { $binary = 1 unless $text || $portable }
+if ($isDOSish) { $binary = 1 unless $text || $UNIVERSAL || $portable }
 
-my $modesym = $binary ? '*' : ($portable ? '?' : ($BITS ? '^' : ' '));
+my $modesym = $binary ? '*' : ($UNIVERSAL ? 'U' :
+               ($BITS ? '^' : ($portable ? '?' : ' ')));
 
 
        ## Read from STDIN (-) if no files listed on command line
@@ -192,7 +232,8 @@ my $modesym = $binary ? '*' : ($portable ? '?' : ($BITS ? '^' : ' '));
 sub sumfile {
        my $file = shift;
 
-       my $mode = $portable ? 'p' : ($binary ? 'b' : ($BITS ? '0' : ''));
+       my $mode = $binary ? 'b' : ($UNIVERSAL ? 'U' :
+                       ($BITS ? '0' : ($portable ? 'p' : '')));
        my $digest = eval { $module->new($alg)->addfile($file, $mode) };
        if ($@) { warn "shasum: $file: $!\n"; return }
        $digest->hexdigest;
@@ -224,7 +265,7 @@ sub verify {
        my $checkfile = shift;
        my ($err, $fmt_errs, $read_errs, $match_errs) = (0, 0, 0, 0);
        my ($num_lines, $num_files) = (0, 0);
-       my ($bslash, $sum, $fname, $rsp, $digest);
+       my ($bslash, $sum, $fname, $rsp, $digest, $isOK);
 
        local *FH;
        $checkfile eq '-' and open(FH, '< -')
@@ -235,7 +276,7 @@ sub verify {
                next if /^#/; s/\n$//; s/^[ \t]+//; $num_lines++;
                $bslash = s/^\\//;
                ($sum, $modesym, $fname) =
-                       /^([\da-fA-F]+)[ \t]([ *?^])([^\0]*)/;
+                       /^([\da-fA-F]+)[ \t]([ *?^U])([^\0]*)/;
                $alg = defined $sum ? $len2alg{length($sum)} : undef;
                $fname = unescape($fname) if defined $fname && $bslash;
                if (grep { ! defined $_ } ($alg, $sum, $modesym, $fname)) {
@@ -247,17 +288,18 @@ sub verify {
                }
                $fname =~ s/\r$// unless -e $fname;
                $rsp = "$fname: "; $num_files++;
-               ($binary, $portable, $text, $BITS) =
-                       map { $_ eq $modesym } ('*', '?', ' ', '^');
+               ($binary, $text, $UNIVERSAL, $BITS, $portable) =
+                       map { $_ eq $modesym } ('*', ' ', 'U', '^', 'p');
+               $isOK = 0;
                unless ($digest = sumfile($fname)) {
                        $rsp .= "FAILED open or read\n";
                        $err = 1; $read_errs++;
                }
                else {
-                       if (lc($sum) eq $digest) { $rsp .= "OK\n" }
+                       if (lc($sum) eq $digest) { $rsp .= "OK\n"; $isOK = 1 }
                        else { $rsp .= "FAILED\n"; $err = 1; $match_errs++ }
                }
-               print $rsp unless $status;
+               print $rsp unless ($status || ($quiet && $isOK));
        }
        close(FH);
        unless ($num_files) {